<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[The Present of Coding]]></title><description><![CDATA[Writing about topics in data science, coding, and Large Language Models. ]]></description><link>https://presentofcoding.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!5n2J!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd24cff60-c536-4be3-b5e7-e9c00c79e816_664x664.png</url><title>The Present of Coding</title><link>https://presentofcoding.substack.com</link></image><generator>Substack</generator><lastBuildDate>Sun, 12 Jul 2026 16:16:39 GMT</lastBuildDate><atom:link href="https://presentofcoding.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Abigail Haddad]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[presentofcoding@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[presentofcoding@substack.com]]></itunes:email><itunes:name><![CDATA[Abigail Haddad]]></itunes:name></itunes:owner><itunes:author><![CDATA[Abigail Haddad]]></itunes:author><googleplay:owner><![CDATA[presentofcoding@substack.com]]></googleplay:owner><googleplay:email><![CDATA[presentofcoding@substack.com]]></googleplay:email><googleplay:author><![CDATA[Abigail Haddad]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Please Let Me Get You Federal Data]]></title><description><![CDATA[Are you a Congressional staffer or journalist? Let&#8217;s talk!]]></description><link>https://presentofcoding.substack.com/p/please-let-me-get-you-federal-data</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/please-let-me-get-you-federal-data</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Wed, 08 Jul 2026 12:03:27 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/39e0aace-ea2c-4cb8-ad4a-1f5b9d88f584_2720x1360.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><span>Last year, a friend asked me a question about government hiring. There are different &#8220;authorities&#8221;&#8212;basically, rules Congress has made&#8212;that let the executive branch hire civil servants. He wanted to know which agencies and positions were using &#8220;direct hire.&#8221;</span></p><p><span>Here&#8217;s how I found it:</span></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><ol><li><p><span>There&#8217;s an API for past USAJobs postings. It doesn&#8217;t have direct hire information, but you can use it to construct the links for each job posting, like </span><a href="https://www.usajobs.gov/job/843514300"><span>this</span></a><span>.</span></p></li><li><p><span>Once you have those links, you can scrape them and pull all of the text on the pages.</span></p></li><li><p><span>Once you have that, you can look for mentions of &#8220;direct hire&#8221;&#8212;but you can&#8217;t just count those up. You also have to figure out which broader text patterns actually mean they&#8217;re using direct hire, versus which ones are using the phrase some other way.</span></p></li></ol><p><span>To do this, you need to know a little about the data set, and then you have to write some code. Most policy-relevant data questions are like this: the data is public, but that doesn&#8217;t mean it&#8217;s easy to answer the question.</span></p><p><span>And if you&#8217;re a journalist or Congressional staffer, you&#8217;re probably not doing this. You don&#8217;t have time, and you&#8217;re a generalist in a lot of things, not an expert in the data set I happen to have spent large parts of the last decade working on. (I was a data scientist for the government, first at Army and then in the DHS AI Corps.)</span></p><p><span>So here's what I'm doing: building open-source tooling for answering policy questions with public data. If you&#8217;re a journalist or Congressional staffer interested in something answerable with specific public data sets&#8212;the </span><a href="https://data.blazingstaranalytics.com/"><span>budget data Joe Carlile is making available</span></a><span>, </span><a href="https://www.makegov.com/"><span>the spending data from MakeGov</span></a><span>, </span><a href="https://data.opm.gov/get-data/data-downloads"><span>EHRI federal personnel data from OPM</span></a><span>, or </span><a href="https://www.usajobs.gov/"><span>USAJobs data</span></a><span>&#8212;I will do my best to answer it for you.</span></p><p><span>And if you&#8217;re a researcher or data person who wants to volunteer&#8212;particularly if you know budget or spending data better than I do, or there are other data sets you want to offer to represent&#8212;please reach out. I&#8217;ll happily hand that part off.</span></p><h2><span>The Data Sets</span></h2><p><span>These are the data sets I can work with:</span></p><p><strong><span>EHRI:</span></strong><span> This is civil servant personnel data: monthly employment, accessions, and separations. It goes back to 2005, and it&#8217;s where to go if you want to answer questions like &#8220;how many lawyers work at DOJ, and how has that changed in the last year?&#8221;</span></p><p><span>This is also the easiest to work with yourself: OPM has done a fantastic job with their business intelligence tools, so you may be able to get what you need just from </span><a href="https://data.opm.gov/explore-data/data/table-builder"><span>the table builder</span></a><span> without coding or talking to anyone. There&#8217;s also a link to the data dictionary on that page, and that can get you started with what the variables mean. But if you have additional questions&#8212;some examples of recent ones I&#8217;ve gotten include &#8220;how do you identify middle management?&#8221; and &#8220;if we&#8217;re trying to tell a story about human capital and difficulty replacing people, what would we look at?&#8221;&#8212;I can help.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rVjF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rVjF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 424w, https://substackcdn.com/image/fetch/$s_!rVjF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 848w, https://substackcdn.com/image/fetch/$s_!rVjF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 1272w, https://substackcdn.com/image/fetch/$s_!rVjF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rVjF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:558770,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/205696018?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rVjF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 424w, https://substackcdn.com/image/fetch/$s_!rVjF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 848w, https://substackcdn.com/image/fetch/$s_!rVjF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 1272w, https://substackcdn.com/image/fetch/$s_!rVjF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3197a27-76d0-4949-86a6-43b9c798f1bb_1700x956.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is OPM&#8217;s Table Builder</figcaption></figure></div><p><strong><span>USAJobs:</span></strong><span> This is the listing of federal jobs data. It isn&#8217;t all federal jobs&#8212;some agencies don&#8217;t list everything on USAJobs. And there&#8217;s also no 1:1 relationship between job listings and hires: listings can result in zero, one, or many hires.</span></p><p><span>Despite these issues, USAJobs is a gold mine for answering certain questions about federal hiring that you can&#8217;t get from EHRI. USAJobs lets you see titles, the full text of duties and requirements, and other text data like those direct hire designations. It&#8217;s also a leading indicator of hiring, because hiring takes a long time, so trends may show up in USAJobs before they show up in accessions data.</span></p><p><span>If you want a sense of what this data looks like&#8212;or want to poke at it yourself&#8212;I&#8217;ve built a site for exploring the postings: </span><a href="https://usajobs-historical.vercel.app/"><span>usajobs-historical.vercel.app</span></a><span>. And this will let you do your own self-service analytics: you can filter by variables like title, occupation, agency, and opening date, and download both summary statistics and the raw data with links to each job posting. But it doesn&#8217;t have the full job listing text data and, like with EHRI, you may have other questions.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MNtR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MNtR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 424w, https://substackcdn.com/image/fetch/$s_!MNtR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 848w, https://substackcdn.com/image/fetch/$s_!MNtR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 1272w, https://substackcdn.com/image/fetch/$s_!MNtR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MNtR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png" width="1456" height="518" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:518,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:533364,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/205696018?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MNtR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 424w, https://substackcdn.com/image/fetch/$s_!MNtR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 848w, https://substackcdn.com/image/fetch/$s_!MNtR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 1272w, https://substackcdn.com/image/fetch/$s_!MNtR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a851c9a-ffe0-4cb7-b0f9-cb752521a76a_2784x990.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://usajobs-historical.vercel.app/">usajobs-historical.vercel.ap</a>p !</figcaption></figure></div><p><strong><span>Budget data:</span></strong><span> </span><a href="https://www.linkedin.com/in/joe-carlile/"><span>Joe Carlile</span></a><span>, formerly of OMB, has made various data sets available, and </span><a href="https://data.blazingstaranalytics.com/"><span>this is my source for budget data</span></a><span>: OMB&#8217;s SF-132 apportionment data, SF-133 execution files, and the President&#8217;s Budget appendix are the main ones I foresee demand for. Others he&#8217;s hosting, like the OMB spend plans, are difficult-to-parse PDFs; I don&#8217;t think I can be useful for those. You can see more on </span><a href="https://data.blazingstaranalytics.com/"><span>his site</span></a><span>. And if this is an interest of yours, you should sign up for his newsletter and potentially hire him&#8212;he&#8217;s the actual guy on this.</span></p><p><strong><span>Contracts and spending data:</span></strong><span> A huge amount of federal contracting data lives on USAspending and SAM.gov. I get some of this from a pipeline I built that pulls in USAspending data and some from </span><a href="https://www.makegov.com/"><span>MakeGov</span></a><span>, which wraps the official sources. The questions you can ask include: what vendors are doing business in my Congressional district? What states and counties are they registered in? What&#8217;s being awarded non-competitively? How has that changed recently? If there&#8217;s a specific FAR rule you want to know what&#8217;s happening under, tell me that.</span></p><h2><span>What I Can Offer</span></h2><p><span>If you&#8217;re a journalist or Congressional staffer and you ask me a question that I think I can answer with one of those data sets, you&#8217;ll get a public GitHub repo with code that processes the data and gets you whatever number, chart, or map you asked for. It will explain in detail what was done and, as best I can, the assumptions I made. It will link to public data so you can verify it yourself&#8212;for instance, if it relies on USAspending data about a particular vendor, it&#8217;ll contain that vendor&#8217;s USAspending link.</span></p><p><span>If it&#8217;s about USAJobs or EHRI, it stands a </span><em><span>really, really</span></em><span> good chance of being accurate. If it&#8217;s about budget or spending data&#8212;I&#8217;m doing my best, but the more details you can give me about what you want, the more likely you are to get what you&#8217;re looking for. If I later find out I did something wrong, I&#8217;ll update the code and let you know as soon as I know.</span></p><p><span>Also tell me your deadline. If it&#8217;s USAJobs or EHRI, turnaround might be hours or faster. If it&#8217;s budget or contracts&#8212;especially if it&#8217;s complicated to me&#8212;it could take longer.</span></p><p><span>On citing me: in general, you shouldn&#8217;t need to, because I&#8217;m giving you the code and the public data. If you want to, that&#8217;s generally fine&#8212;unless it&#8217;s something I&#8217;m not sure of, in which case I&#8217;ll tell you that.</span></p><p><span>I am not offering to make you websites or other permanent infrastructure. I own way too much of that already.</span></p><h2><span>What I Can&#8217;t Offer</span></h2><p><span>Don&#8217;t tell me anything private. I don&#8217;t want constituent data. I am not on FedRAMP. I&#8217;m a person doing this with Claude Code because I believe in data and democracy and those things being related.</span></p><p><span>My preference is that everything I do goes on GitHub and becomes public. I think it&#8217;s possible to abstract this out enough to keep any inquiries private&#8212;for instance, if you care about your specific Congressional district, we can pull data for all districts, not just yours. I&#8217;m also fine with waiting some period of time before making code public&#8212;more like a week than a year.</span></p><p><span>This matters to me partly because I&#8217;m committed to working in public, and partly because if you ever want to hand this over to another data scientist or developer, a public repo will make that easier for you.</span></p><h2><span>How to Reach Out</span></h2><p><span>Try me on Signal at </span><strong><span>abigail.haddad_43</span></strong><span>&#8212;that&#8217;s the best way to get a response. If you&#8217;re reaching out on Signal and I can&#8217;t easily verify who you are, I&#8217;ll ask you to send me an email from an official email address or find me on LinkedIn. If this gets overwhelming for me, I&#8217;ll set up some form of ticketing system that makes these easier to track.</span></p><p><span>Also, this is an experiment! I have no idea how it&#8217;s going to play out, so let&#8217;s see.</span></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[How to Find a Side Project]]></title><description><![CDATA[A few weeks ago when I was in San Francisco for a conference, I saw a mosaic, and I couldn&#8217;t stop looking at it.]]></description><link>https://presentofcoding.substack.com/p/how-to-find-a-side-project</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/how-to-find-a-side-project</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Wed, 24 Jun 2026 12:00:32 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a5a489fc-d9c5-4596-9ffc-29a01973751a_1828x1080.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><span>A few weeks ago when I was in San Francisco for </span><a href="https://less.online/"><span>a conference</span></a><span>, I saw a </span><a href="https://www.ellenharvey.info/wp-content/uploads/2021/06/3d.jpg"><span>mosaic</span></a><span>, and I couldn&#8217;t stop looking at it. It was a map of the city rendered in tile &#8212; gray and white for land and buildings, green for parks. I&#8217;m normally not someone who pays much attention to my visual surroundings. I&#8217;m moderately face blind: you can ask me whether someone I talked to all evening has facial hair and I genuinely won&#8217;t know, and I&#8217;m similarly bad about noticing or remembering artwork or colors. But this immediately felt different. I got as close as I could, and I would have touched it if I thought that were allowed.</span></p><p><span>Partly, I was trying to figure out what information was being encoded: within the overall color groups, did the shade or shape of individual tiles mean anything? I decided they couldn&#8217;t. I also figured out that part of what made it so compelling was that the green and gray tiles came from distinct shape </span><em><span>families</span></em><span> &#8212; the greens had more large outliers, and were far less rectangular than the grays.</span></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><span>That was all I got &#8212; five or ten minutes of staring at it, and I never saw it again.</span></p><p><span>But I couldn&#8217;t get it out of my head. For days after, I was pulling out my laptop at the conference and trying to understand the math of tile generation, wanting to make something similar for DC.</span></p><p><span>It was hard. The standard ways of characterizing tile style for mosaics didn&#8217;t work. With Claude Code, we measured the actual tiles from a photo online, mapped them to coordinates, built a generator tuned to match certain shape metrics &#8212; and the output still looked wrong. What finally worked was keying directly off the shapes themselves and defining our own metrics. The gray tiles, for instance, have a lot of 80&#8211;100 degree angles &#8212; not exactly 90, but close enough that they read as rectangular. I guided Claude Code to that, and I was happy with </span><a href="https://us-mosaic-greenmap.netlify.app/"><span>how it ended up</span></a><span>.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OMst!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OMst!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 424w, https://substackcdn.com/image/fetch/$s_!OMst!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 848w, https://substackcdn.com/image/fetch/$s_!OMst!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!OMst!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OMst!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg" width="430" height="526.75" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1274,&quot;width&quot;:1040,&quot;resizeWidth&quot;:430,&quot;bytes&quot;:190163,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/203237537?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OMst!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 424w, https://substackcdn.com/image/fetch/$s_!OMst!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 848w, https://substackcdn.com/image/fetch/$s_!OMst!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!OMst!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85c224c1-8e91-4292-a4e5-606b77566aaa_1040x1274.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is my <a href="https://us-mosaic-greenmap.netlify.app/#state=district_of_columbia&amp;land=quads&amp;parks=shards&amp;water=flow">DC map</a></figcaption></figure></div><h2>Noticing becomes a project</h2><p>My mom once let a stray cat onto her porch during a storm. Later that night a second one showed up and insisted on coming in, and that's how we ended up with two cats. Side projects work the same way: you get interested in X, you do X, you notice the gaps and the new questions, and at some point you have more than you can manage. From the original map, I digressed into whether 3D printing any of it was feasible (it's not, at a price I'd pay), then into the math of tiling more broadly, then into <a href="https://abigailhaddad.github.io/million-tiles/">population density</a>, and now I'm working on another map combining the mosaics with using color to denote population. </p><p><span>So when people ask how to find side projects, I sort of joke: at this point I have to try harder not to find them. You take one in and suddenly the whole neighborhood knows you&#8217;re a sucker. But really, I think it&#8217;s a pattern of thought you develop that starts with noticing certain kinds of things in the world. Noticing &#8220;I find this incredibly compelling&#8221; or &#8220;I want to know how this works&#8221; or &#8220;something is missing here&#8221; &#8212; and that last one can mean a lot of things, from &#8220;this community needs an event&#8221; to &#8220;someone should answer this question.&#8221; It&#8217;s noticing, and then going from that to &#8220;I could do something about this.&#8221;</span></p><p><span>The first projects are the hardest because you haven&#8217;t built that reflex yet. At this point, matching what I observe to &#8220;I could build something here&#8221; is annoyingly everywhere &#8212; and Claude Code has dramatically expanded my sense of what I&#8217;m capable of building, which is part of why mosaic tiles are apparently in scope for me now. (Though if I hadn&#8217;t already done a lot of map work right before that trip, I&#8217;m not sure I would have felt equipped to try.)</span></p><p><span>Another thing that&#8217;s shifted: I used to start projects as open-ended explorations, which meant they went on indefinitely and never shipped. Now I tend to have a clear picture of what I&#8217;m making before I start, and I think that makes it feel lower-stakes: maybe I&#8217;m fostering the stray cat rather than adopting it.</span></p><h2><span>Hit at least one of these criteria</span></h2><p><span>A project needs to hit at least one of these for me.</span></p><p><strong><span>Is it fascinating or beautiful?</span></strong><span> The mosaic was, immediately and obviously. Sometimes I pull up the finished maps just to look at them. There are things I&#8217;m wired to find compelling, and that set has grown over the last few years &#8212; partly because Claude Code lets me get into subjects that used to require a lot of prerequisite learning before they were accessible to me.</span></p><p><strong><span>Is it useful to me to make this?</span></strong><span> Sometimes this is about learning something I need to have: I did work with sam.gov and USASpending because I needed to understand federal procurement data well enough to answer certain types of questions about it. Or last year, when I was actively job-hunting, I took a day off specifically to build something I could talk about in interviews.</span></p><p><strong><span>Is it useful for this to exist?</span></strong><span> Sometimes I just want a thing to exist in the world, either for me or for someone else. In those cases, if I can get someone else to do it, that&#8217;s fantastic.</span></p><h2><span>The people you meet along the way</span></h2><p><span>One of my side projects is that I run a </span><a href="https://partiful.com/e/geiJzZHknytQn4BPxNvZ"><span>monthly happy hour</span></a><span> for civic tech people. It started partly because I was a fed for the first part of 2025, it was bad, and I wanted in-person spaces to connect that didn&#8217;t yet exist.</span></p><p><span>And </span><a href="https://presentofcoding.substack.com/i/179102693/finding-ideas"><span>being in spaces</span></a><span> where people talk about things they care about is one of the best ways to find the next project &#8212; someone names a problem, other people riff on it, and you see the gap. But it&#8217;s also a flywheel: you make something, you share it, you meet people through it, and those people pull you into new spaces with new problems and new ideas.</span></p><h2><span>What LLMs do and don&#8217;t do (yet?)</span></h2><p><span>With the mosaic, Claude Code struggled early on. It couldn&#8217;t tell that the tiles it was generating didn&#8217;t look like what I wanted, and it kept insisting they did. I was doing a lot of hand-holding. But once I&#8217;d worked out the approach with it, it generated the code much more quickly and better than I would have.</span></p><p><span>The way I&#8217;d describe the current dynamic: the models are good at execution, and much of the interesting work &#8212; figuring out what to make, diagnosing what&#8217;s wrong, deciding what matters &#8212; still largely comes from me. This is a description of the technology as it is right now, not an eternal claim about what humans bring that machines never will. Model quality is improving fast. But at the moment, there&#8217;s still a lot of fun in the gap for me &#8212; especially the ability to dabble in math I never formally learned, to have an intuition about what should happen when I change a parameter and then find out if I&#8217;m right.</span></p><h2><span>It doesn&#8217;t need to be good</span></h2><p><span>Seven years ago, I modeled </span><a href="https://github.com/abigailhaddad/sock_fairy/blob/master/.ipynb_checkpoints/Socks-checkpoint.ipynb"><span>sock loss</span></a><span>. My kids were small, I wasn&#8217;t sleeping much, and I had become convinced that I was losing the first sock of each pair at a disproportionate rate &#8212; that my personal sock-loss distribution was non-random in a specific and maddening way. So I modeled it: if you lose socks uniformly at random, what share end up unpaired as a function of the percentage of socks you&#8217;ve lost? This is a trivial problem. But it was a lot of fun, and I&#8217;m glad I did it.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cBc8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cBc8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cBc8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cBc8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cBc8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cBc8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg" width="574" height="341.7526205450734" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:568,&quot;width&quot;:954,&quot;resizeWidth&quot;:574,&quot;bytes&quot;:51157,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/203237537?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cBc8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cBc8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cBc8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cBc8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ba6d9ef-2e21-4b07-9dd5-ad482b5d87db_954x568.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I was -not- necessarily losing socks in a worse-than-random pattern</figcaption></figure></div><p><span>I&#8217;ve also made things that were technically bad &#8212; a genuinely awful RAG chatbot for answering questions about making Quarto presentations, for instance. I learned things about RAG chatbots in the process. Someone later built something dramatically better that incorporated that functionality, and seeing it I thought: oh, obviously I was not the person who was going to do a good job with that. But that was fine.</span></p><p><span>If you&#8217;re concerned about quality &#8212; you want feedback on how you&#8217;re approaching something technically &#8212; ask for it. I almost never offer this unsolicited, but I find it very useful when I get this from other people.</span></p><h2><span>Don&#8217;t go to the pet store</span></h2><p>How do I find projects? I notice them &#8212; and then I let them in. Because I source my own from the world around me instead of pulling pre-packaged ones off Kaggle, they've never once bored me. The projects no one else would have thought to do &#8212; the ones that are specifically yours &#8212; are the ones you'll most enjoy working on and the ones people most enjoy hearing about. Earnest fascination is contagious. Follow the thing you can't stop looking at, and you'll ask the best questions and build the best things out of it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[My Blog Post Is the Exploit]]></title><description><![CDATA[Each new model changes the math]]></description><link>https://presentofcoding.substack.com/p/my-blog-post-is-the-exploit</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/my-blog-post-is-the-exploit</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Wed, 17 Jun 2026 12:01:41 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/46fb2bf7-4b6b-4bf5-95b1-367f564bebc0_1122x1402.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In 2024 I wrote a <a href="https://presentofcoding.substack.com/p/inferring-suppressed-data">blog post about a government data set with suppressions in it</a> &#8212; data that had been taken out to be less identifiable &#8212; where it was possible to use algebra to fill in a lot of the missing data.</p><p>For years, I&#8217;ve now been using this problem as my own benchmark for ChatGPT<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>, and then Claude, and then Claude Code. I give the model the blog post and the latest data &#8212; but none of the code I wrote &#8212; and see if it can correctly write new code to solve the problem.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Prior to last week, this had gone badly. It&#8217;s not that this is especially complicated. But it is a weird problem: the data is messy in multiple unexpected ways, and I use a Python package to solve it that&#8217;s not exactly obscure, but it&#8217;s also not pandas.</p><p>The last time I tried this with Claude Code, in late 2025, we went back and forth with it confidently telling me it had solved the problem &#8212; and then I&#8217;d look at the numbers it had found, and they would be immediately and obviously incorrect. (Think: negative numbers of people.) I spent hours going back and forth giving it hints, but it still failed.</p><p>So when <a href="https://www.anthropic.com/claude/fable">Fable</a> came out, and I heard it was really good at one-shotting complicated problems, I tried once again giving it just the data and my blog post. And with almost no additional guidance from me &#8212; I told it one fact about how the newest data was differently-structured than the file I&#8217;d written about &#8212; it correctly wrote the code. And when prompted lightly, it improved the code from how I&#8217;d done it, finding a different package I didn&#8217;t know about that could do part of the work at a much faster pace<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>.</p><p>That a description of a solution can increasingly generate working code &#8212; no coding or subject matter expertise required &#8212; changes the math on disclosure of exploits. If you&#8217;re counting on limited expertise or will being the thing that protects your data or your system, that continues to be an ever-worse bet.</p><h2><strong>The Original Problem</strong></h2><p>DC releases a huge amount of standardized test score data every year. Much of it is suppressed to protect student privacy &#8212; they don&#8217;t want people to be able to identify individual students&#8217; test scores by knowing facts about them, like their school, grade, and race.</p><p>But the specific way the suppression is done never made sense to me.</p><p>The published numbers are linearly related &#8212; that is, they can be reduced to systems of linear equations. Data appears at multiple levels of aggregation: performance levels 1&#8211;5 (but also rolled up as 3+ and 4+), school, school &#215; grade, and school &#215; grade &#215; race. State- and LEA-level data (Local Education Agency &#8212; the public school system and each charter school or network) add further constraints. By setting up and solving these systems, you can recover a lot of the missing values.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nQfY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nQfY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 424w, https://substackcdn.com/image/fetch/$s_!nQfY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 848w, https://substackcdn.com/image/fetch/$s_!nQfY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 1272w, https://substackcdn.com/image/fetch/$s_!nQfY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nQfY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png" width="497" height="353.34160583941605" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:974,&quot;width&quot;:1370,&quot;resizeWidth&quot;:497,&quot;bytes&quot;:105576,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/201680533?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!nQfY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 424w, https://substackcdn.com/image/fetch/$s_!nQfY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 848w, https://substackcdn.com/image/fetch/$s_!nQfY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 1272w, https://substackcdn.com/image/fetch/$s_!nQfY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b99da3f-384b-4806-b396-328fc3a0c2fd_1370x974.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A refresher on systems of linear equations</figcaption></figure></div><h2><strong>What the Exploit Gets You</strong></h2><p>There are no names in these files &#8212; you can't look anyone up. But individual test results can be recovered in very specific circumstances: when a demographic slice at a school is small or homogeneous enough that every child in it received the same score. If you already know a specific child belongs to that group, you now know whether they tested proficient. At the finest cross-tabs &#8212; school &#215; grade &#215; demographic &#8212; roughly 7,500 results become readable this way. Most of what leaks is "this child did not reach proficiency." In far more cases, though, you can rule out that a child scored at a particular level &#8212; most often, the top score.</p><p>But this is not really the point of the post: you can think it&#8217;s really bad for this information to be inferrable, or not bad at all. The point is that <em>what protected this data wasn&#8217;t the suppression design &#8212; it was that almost nobody who might want this data could write the code to exploit it</em>. That barrier is now gone.</p><h2><strong>Who Does This Matter For?</strong></h2><p>If the only thing standing between your data, your system, or your process and misuse is &#8220;most people couldn&#8217;t figure out how to do this&#8221; &#8212; you should go test that assumption with the latest model. And if it fails now, keep testing it as new models come out.</p><p>For instance: if you&#8217;re a company that gives take-home exercises to job candidates, put yours into Claude Code and see what comes back. If you&#8217;ve ever written up a vulnerability in prose and not published proof-of-concept code because you figured that was enough protection, test it. Anywhere you&#8217;ve said &#8220;yes, but you&#8217;d need to know X to do that to our system&#8221; &#8212; where X is something a new model might be able to do &#8212; that sentence is worth revisiting and continuing to revisit.</p><p>I&#8217;ve been using this problem as my own benchmark because I wanted to know when that line got crossed. Well, that happened.</p><p>When I wrote this up in 2024, I didn&#8217;t share the code or the recovered data. It felt wrong. I knew realistically that probably no one else was going to go through the trouble of figuring out how to code this thing, because that would have required a pretty niche skill set and the willingness to spend a real chunk of time doing it.</p><p>And I&#8217;m <em>still</em> not publishing the code or the recovered data. Partly I&#8217;m afraid of getting into legal trouble, partly it still just feels wrong to publish children&#8217;s data, even if I&#8217;m not the person responsible for safeguarding it and it&#8217;s been <em>over three years</em> on this.</p><p>But here&#8217;s what I can tell you. I found this problem in 2022 and I had to solve it. I did a proof of concept in Excel first to make sure what I thought I saw was indeed there. Then &#8212; and this was before ChatGPT &#8212; I sat down and wrote some egregiously bad code that weekend as fast as I could to get to the basic answer. In the years after that I rebuilt it properly, added tests, and studied the problem. I know this topic <em>well</em>.</p><p>And if you&#8217;re curious, you can take my old blog post, put it into Fable, and in an afternoon, you will have access to all of the same code and results that I do<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Initially, this was less out of curiosity and more because I wanted it to update my code for newly-released and differently-formatted data sets.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>For the sake of thoroughness, I went back and tried this with Opus. It worked much better than prior models, but it also made several mistakes that Fable didn&#8217;t make, and it only self-corrected on one of them.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>Or you could, <a href="https://www.anthropic.com/news/fable-mythos-access">prior to all of this</a>.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Your AI Lead Should Be an Engineer]]></title><description><![CDATA[AI is not a job description]]></description><link>https://presentofcoding.substack.com/p/your-ai-lead-should-be-an-engineer</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/your-ai-lead-should-be-an-engineer</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Thu, 11 Jun 2026 12:01:33 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/68481eb4-a487-4cd8-8731-3616271606db_1537x1023.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;m increasingly seeing job postings for &#8220;be the person who tells us how to use AI.&#8221; They typically bundle in building out internal &#8216;AI workflows&#8217; to automate processes, assisting with acquisition decisions, and integrating commercial tools into the organization&#8217;s setup.</p><p>I&#8217;ve done these tasks, and some of them I&#8217;ve even done well. If you insist on this role being one person because that&#8217;s what you have money or the billet to hire for, you should hire an engineer. By an engineer, I mean <strong>someone who has written a lot of code, is familiar with software development practices, and is going to be comfortable hands-on building out tooling</strong>, even if they&#8217;re not coming from a traditional software development background.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>This is because there is no such thing as an &#8216;AI workflow&#8217; for automation that doesn&#8217;t include traditional engineering. There are only data pipelines with AI components. Building AI tools is engineering+, not engineering-.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rS4e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rS4e!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!rS4e!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!rS4e!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!rS4e!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rS4e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png" width="494" height="329.44642857142856" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:494,&quot;bytes&quot;:2398183,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/201450566?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rS4e!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!rS4e!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!rS4e!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!rS4e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F255d2604-b16a-47d3-8a78-6f45ba9c9b1b_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A data pipeline: data goes in, gets transformed at each step, and comes out the other end as something useful</figcaption></figure></div><h1><strong>Let&#8217;s Look at This Job Posting</strong></h1><p>Here&#8217;s an excerpt from the skills and experience section of a recent posting I came across, lightly anonymized.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/pxf6H/2/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/67f4bdc0-fcb3-41f4-9644-2882d322fdb9_1220x834.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a67a0250-63ef-4fe6-915b-121d43245349_1220x744.png&quot;,&quot;height&quot;:450,&quot;title&quot;:&quot;Skills&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/pxf6H/2/" width="730" height="450" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>None of the following words or phrases appear anywhere in this posting: software, code, engineering, data pipeline. And yet: connecting to external tools via APIs is coding. Collecting, cleaning, and reporting on large amounts of data is data engineering. Building a CRM with robust data modeling and normalization logic is an engineering project. These tasks have nothing to do with AI beyond potentially enabling it &#8212; they&#8217;re completely standard engineering tasks.</p><p>The bullet I want to spend the most time on is &#8220;designing AI workflows to automate processes.&#8221; There is no such thing as an AI workflow for automation &#8212; there are only data pipelines with AI components, and you may not even know if you need an AI component until you sit down and scope it.</p><h1><strong>What Is an &#8216;AI Workflow&#8217;?</strong></h1><p>The simplest AI workflow I&#8217;ve ever done professionally looked like this:</p><ol><li><p><strong>Pull data</strong> from an existing database via a SQL query</p></li><li><p><strong>Deduplicate and clean the data</strong>, which involved making specific calls about what constituted a duplicate</p></li><li><p><strong>Send each row to an LLM via API calls</strong>, along with a prompt, and get the results back</p></li><li><p><strong>Build an evaluation harness</strong> to try out different prompts and measure accuracy against human labels</p></li><li><p><strong>Build tables and visualizations</strong> to display the results</p></li><li><p><strong>Handle data storage</strong> so when new data comes in, you don&#8217;t waste API calls on data you&#8217;ve already run</p></li><li><p><strong>Push to GitHub</strong></p></li></ol><p>This is basically just data science. Knowing only how to make an API call to an LLM does not get you anything without the rest of it.</p><p>And most of the workflows I build that incorporate AI are considerably more complicated from an engineering perspective. I&#8217;m usually not handed the data &#8212; I&#8217;m building a pipeline to pull it from wherever it lives, which frequently involves web scraping. My data cleaning and analysis workflow nearly always has more moving parts. I&#8217;m often building a website to display the results. More real automation &#8212; things that run in real-time in response to a user action, or that integrate with your existing databases, or that make a decision for you &#8212; require even more of a software-building skill set<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>.</p><p>How much can you vibe-code this? To some extent. But we&#8217;re not at the point where you don&#8217;t need<em> some </em>background. If your toolbox is only AI, you will reach for AI whether or not it&#8217;s the right tool, and you probably don&#8217;t even have a good sense of which AI component to use.</p><p>What about no-code tools? For some bounded, well-defined tasks, those will work. But for the kinds of custom pipelines with AI components that I see in real life, the tooling just isn&#8217;t there yet. </p><p>Web scraping a site that doesn&#8217;t want you to scrape it, where the formatting varies considerably page-to-page, may require a workflow that combines LLM API calls to discover structure along with data processing, if what you want is a repeatable, transparent process<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. Using agents and also building an evaluation harness that can tell you what tool calls they&#8217;re making and how variable this is across runs requires code. </p><p>The problem with hiring someone who&#8217;s only comfortable with no-code tools isn&#8217;t that they can&#8217;t build anything &#8212; it&#8217;s that you&#8217;re going to hit a wall, and you can&#8217;t know before you invest the time scoping out projects how much of a limitation this will present.</p><p>This matters for what skills you look for and how you describe the role, and it matters for salary: if you set the salary at &#8220;generalist business analyst,&#8221; you will not get this skill set.</p><h1><strong>Don&#8217;t Be Like Data Science</strong></h1><p>Data science had a significant mismatch between requirements, duties, and desired outcomes, and it did not go well. Organizations hired data scientists expecting someone to come in and &#8220;make their data useful.&#8221; What the data scientists got instead was data engineering, data cleaning, and building dashboards &#8212; and everyone was disappointed.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k0Z1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k0Z1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!k0Z1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!k0Z1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!k0Z1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k0Z1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg" width="402" height="402" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:500,&quot;width&quot;:500,&quot;resizeWidth&quot;:402,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!k0Z1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!k0Z1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!k0Z1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!k0Z1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99961359-c4ff-474d-83b0-30c1d970fda0_500x500.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Actual image of what happened</figcaption></figure></div><p>And &#8220;make our data useful&#8221; was also never something one data scientist could come in and do. It takes organizational buy-in, a data infrastructure that&#8217;s already in place, and a lot of scoping before you can determine whether any particular project is feasible and what it needs. The same is true now with AI. Hiring an &#8220;AI person&#8221; and expecting them to transform how your organization works will produce the same result: a frustrated person doing work they didn&#8217;t sign up for, and an org that&#8217;s not getting what it thought it was buying.</p><p>What does being ready look like? Some of it is data access: your data needs to live somewhere that allows integrations with their tooling, and you need to be willing to grant them.</p><p>Some of it is willingness to change. For organizations that run heavily on Excel for analytics, a lot of the available gains from AI only materialize if you&#8217;re willing to move to code-based workflows. An engineer can help you get there, but they can&#8217;t make your staff do that.</p><p>And some of it is just your time. AI coding tools allow for building quickly, which means the person you hire needs fast feedback loops. If stakeholders aren&#8217;t available to weigh in, that&#8217;s a bottleneck.</p><p>&#8220;AI&#8221; is not a job the way &#8220;software developer&#8221; or &#8220;data engineer&#8221; is a job. It&#8217;s a problem space. Figure out what problems you&#8217;re trying to solve and whether you&#8217;re set up to solve them &#8212; and if you are, hire an engineer.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>A note on &#8220;engineer&#8221;: the right flavor depends on what you&#8217;re building. If you want event-driven, user-facing products &#8212; a button that triggers a model, a real-time chatbot &#8212; that&#8217;s a software engineer. If you want classification models with rigorous evaluation pipelines, that&#8217;s closer to data science. I think the coding-versus-not-coding distinction matters more than which of those you hire for. But if you want both &#8212; real data software with mature analytics &#8212; that&#8217;s a team, not a person.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Which you SHOULD want, but that&#8217;s another piece.</p></div></div>]]></content:encoded></item><item><title><![CDATA[No, I Don’t Read My Code]]></title><description><![CDATA[And I&#8217;m Happy to Tell You Why]]></description><link>https://presentofcoding.substack.com/p/no-i-dont-read-my-code</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/no-i-dont-read-my-code</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 08 Jun 2026 15:01:02 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/bdaf8e4d-3976-4fe5-8bbb-4926df0d8b63_1594x987.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last week I was giving a lightning talk about DC real estate data &#8212; how good the data is, and how, with Claude Code, you can quickly answer questions and build great-looking figures. At the end I had a slide listing the tools I&#8217;d used, and I called out Leaflet, which I used to make the maps. Someone in the audience asked me what Leaflet was, and I told them I didn&#8217;t know and they should ask Claude Code.</p><p>I was joking, sort of. Leaflet is a JavaScript library that integrates with OpenStreetMap, which provides the map tiles I was using. I can tell you exactly what I built with it &#8212; a <a href="https://leafletjs.com/examples/choropleth/">choropleth</a> map, a <a href="https://www.dash-leaflet.com/components/vector_layers/circle_marker">proportional-symbol</a> dot map, and a flag-symbol map (one country flag per owner, sized by assessed value).</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YUv2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YUv2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 424w, https://substackcdn.com/image/fetch/$s_!YUv2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 848w, https://substackcdn.com/image/fetch/$s_!YUv2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 1272w, https://substackcdn.com/image/fetch/$s_!YUv2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YUv2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png" width="1456" height="765" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:765,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YUv2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 424w, https://substackcdn.com/image/fetch/$s_!YUv2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 848w, https://substackcdn.com/image/fetch/$s_!YUv2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 1272w, https://substackcdn.com/image/fetch/$s_!YUv2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49db86a-adff-4636-8ad9-72681614d5f8_1912x1004.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is a leaflet map of DC properties by when they were built</figcaption></figure></div><p>But if you ask me about the code itself, I can&#8217;t tell you much. I can&#8217;t tell you the syntax. I can&#8217;t tell you which Leaflet functions I called, or even very much about JavaScript as a language. That&#8217;s because, with Claude Code, the level of abstraction I&#8217;m working at is very different from when I was writing code by hand. Sometimes I glance at a few lines of code while Claude Code is writing it, or when we&#8217;re refactoring together. But I almost never open an actual file and read it from start to finish.</p><p>I think this is reasonable. And I think if you&#8217;re an engineering leader &#8212; or anyone who talks to people about coding practices &#8212; part of your job is asking which practices still make sense given where the tooling is and where it&#8217;s going. What were we trying to get by reading code, and are there better ways of getting it now? How does this depend on what we&#8217;re building and on the stage of development of the product? The answers to these are different than they were two years ago, and they&#8217;re going to keep changing.</p><h2><strong>Modeling vs. understanding</strong></h2><p>I&#8217;m told that coding sorting algorithms is a standard activity in introductory computer science classes &#8212; there are sorting algorithms of different degrees of efficiency, and students come out of it understanding how they differ and how to build each of them.</p><p>Even before LLMs, that wouldn&#8217;t have been especially useful to my work as a data scientist. The things I needed to know about sorting algorithms were essentially: what&#8217;s the syntax, and how do they behave on my data? I can still recall a couple of the parameters in the sort function that I used the most, and at one point I probably needed to know what happens if you sort a series with both numbers and letters. But that&#8217;s as far as I would have gone.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y9on!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y9on!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 424w, https://substackcdn.com/image/fetch/$s_!y9on!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 848w, https://substackcdn.com/image/fetch/$s_!y9on!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 1272w, https://substackcdn.com/image/fetch/$s_!y9on!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y9on!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png" width="1456" height="891" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:891,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y9on!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 424w, https://substackcdn.com/image/fetch/$s_!y9on!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 848w, https://substackcdn.com/image/fetch/$s_!y9on!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 1272w, https://substackcdn.com/image/fetch/$s_!y9on!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd42e0e82-92f5-457f-ae73-cb0ea8aef229_1644x1006.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is the kind of documentation/level of understanding that was useful to me as a data scientist: what is the function, what parameters does it take, what are examples of its usage?</figcaption></figure></div><p>Are data scientists bad coders because they don&#8217;t know which algorithms their tools are using to sort, and couldn&#8217;t derive them?</p><p>I don&#8217;t think they are. What coders always need isn&#8217;t full understanding &#8212; it&#8217;s to be able to model their code at a level appropriate to their goals.</p><p>What I mean by modeling is: I hold a picture of what my code does at the level of inputs, outputs, and behavior. If I run this pipeline on this data, here&#8217;s what I expect to come out. Here&#8217;s what would surprise me. Here&#8217;s where it&#8217;s most likely to break, and here&#8217;s what I&#8217;d see if it did.</p><p>I used to get that in part by reading my code. How I get it is different now. And how much of it I need depends on what I&#8217;m building.</p><p>For a prototype &#8212; something exploratory I&#8217;m building to figure out what I want to make &#8212; I might barely need it at all. What I&#8217;m making might just be a glorified wire frame, meant to show the layout and what happens when you click.  For something in production, I need a lot more: I know from experience that, while Claude Code can help enormously with this, I still need to model my code well enough to catch issues and build on it. How much that changes as the tooling improves, I don&#8217;t know.</p><h2><strong>Your attention is now expensive</strong></h2><p>I write so many more tests than I used to.</p><p>It&#8217;s not that I never wrote tests before LLMs. It&#8217;s that they weren&#8217;t a regular part of my practice as a data scientist. Now they&#8217;re a default. Anything breaks, write a test for it. The cost of writing the test is cheap, and the benefit &#8212; never manually testing that thing again, never worrying it broke without my noticing &#8212; is high.</p><p>This is because my attention is now what&#8217;s expensive.</p><p>Old practices were optimizing against the cost of writing code. That cost is gone. Most things in the development workflow that used to be expensive &#8212; tests, refactoring, documentation, exploration &#8212; are now cheap. The only expensive thing left is your attention.</p><p>That changes which practices are worth investing in. The answer to &#8220;what should we do more of?&#8221; is: almost everything that protects code quality <em>without costing a lot of your own attention</em>.</p><p>Write more tests, no matter what kind of code you&#8217;re writing. Write them as a default, not a chore at the end of a project. Refactor more often, in smaller chunks, as a normal part of working. Open more pull requests, in smaller pieces, and if you&#8217;re running an engineering team, raise the bar for what gets merged &#8212; because the cost of improving code has dropped.</p><p>Your attention is the budget. Spend it on what only your attention can do: what to build, whether the artifact is meeting the goal, where the design is wrong. Don&#8217;t spend it on the things the tools now do for you.</p><p>And for each practice we use, we should be able to answer: what are we trying to get from this, and is this still the best way to get it?</p><p>I got asked to give that lightning talk about four days before the event, and I put it together in about an hour. The point I wanted to make was the utility of the data and the ease of building with it. That&#8217;s all. It was uncomfortable having only a surface-level understanding of my code, but that really was the only level I needed to make that point &#8212; and if I&#8217;d needed to have more, I wouldn&#8217;t have had time to make it.</p><h2><strong>To people who haven&#8217;t gotten on board</strong></h2><p>There&#8217;s a lot of evidence about what these tools can do. The benchmarks have been moving for two years. There&#8217;s testimony from developers across the field. For me, there&#8217;s my own 2,000+ hours. All of it points the same direction, which is that these tools are just really good.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bmj3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bmj3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 424w, https://substackcdn.com/image/fetch/$s_!Bmj3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 848w, https://substackcdn.com/image/fetch/$s_!Bmj3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 1272w, https://substackcdn.com/image/fetch/$s_!Bmj3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bmj3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png" width="1456" height="696" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:696,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Bmj3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 424w, https://substackcdn.com/image/fetch/$s_!Bmj3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 848w, https://substackcdn.com/image/fetch/$s_!Bmj3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 1272w, https://substackcdn.com/image/fetch/$s_!Bmj3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b6a04db-02e6-417e-aa20-80ccb29fd8c9_2048x979.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is one of the versions of the <a href="https://metr.org/time-horizons/">METR graph</a> of LLMs and software tasks</figcaption></figure></div><p>But I still see a lot of dismissal from software developers, including sneering at people who don&#8217;t read their code.</p><p>I have some sympathy for where the dismissal comes from. When you have a skill that feels central to your professional &#8212; and maybe personal &#8212; identity, and now a piece of software can do it, and so can people who don&#8217;t have your skills but use that software &#8212; it&#8217;s hard. This is something a lot of us are dealing with right now.</p><p>But nonetheless, that is what happened and is continuing to happen.</p><p>And if you&#8217;re going to stay in this field &#8212; and stay in a position of leadership &#8212; you&#8217;re doing the people who depend on you a disservice if you don&#8217;t acknowledge what&#8217;s happening. They need your help figuring out what comes next: what good practice looks like in this new shape, what we should be teaching, what we should be hiring for, how to make the cheap practices stick. That work needs people who care about doing things right and are willing to update their picture of what that looks like.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[A Year After Leaving Government]]></title><description><![CDATA[Having an LLC instead of an employer]]></description><link>https://presentofcoding.substack.com/p/a-year-after-leaving-government</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/a-year-after-leaving-government</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 25 May 2026 12:10:31 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fcc29aa6-8a23-4039-8e2b-418d86293007_1630x1126.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I registered my LLC last year, it was right after I&#8217;d taken the Deferred Resignation Program &#8212; the program whereby the government paid me to leave DHS AI Corps. I needed a name, so I described to Claude what I do, gave it the acronym DRP, and picked my favorite suggestion: Data Research Partners, LLC.</p><p>I wasn&#8217;t thinking about how this name I picked as a bit was going to be on my business cards, my LinkedIn, my tax forms, and my bios when I give talks. That&#8217;s because I didn&#8217;t think I would still be doing this full-time a year from now. I assumed I would do some part-time consulting and then go back to a full-time salaried role. But I haven&#8217;t, and I&#8217;ve had a much better year for it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>This is about why I chose that and what it&#8217;s cost me.</p><h2><strong>What I wasn&#8217;t going to give up</strong></h2><p>AI Corps &#8212; before it collapsed &#8212; had a lot of things that I loved. I got to work on multiple projects at once, sometimes by raising my hand to volunteer, or by putting some work in to build and then saying &#8220;hey, I think we should do more of this.&#8221; I had technical autonomy in the areas where it matters to me. I was getting to grow my career in the ways I wanted, and work on things that mattered to me. I had a level of compensation I was happy with, and I was able to work from home.</p><p>When I left, I didn&#8217;t want to give up any of those things. But the salaried jobs that had all of those attributes weren&#8217;t going to hire me. I&#8217;d gotten engineering interviews through recruiters and my network, but the interviewers could tell immediately I wasn&#8217;t what they were looking for. I don&#8217;t have a STEM or CS background, and I haven&#8217;t worked as a software engineer.</p><p>Meanwhile, unpaid side projects I was doing were leading to meeting people who wanted to work with me, and former coworkers were reaching out as well. When someone&#8217;s hiring for a role, there are a lot of boxes they want to check, and I don&#8217;t typically fulfill those. But when they see what I do &#8212; when they can go, &#8220;Oh, there&#8217;s this person who does these interesting things&#8221; &#8212; they&#8217;re not checking off boxes anymore, and that&#8217;s a much better lane for me.</p><p>It&#8217;s also lower-risk for them: they don&#8217;t have to commit to 40 hours a week. And the comp piece can work out better as well. There are organizations that wouldn&#8217;t pay any engineer the full-time equivalent of what I make, but will make room for a contractor on a fixed number of hours for a specific project.</p><h2><strong>What I do for a living</strong></h2><p>My niche is full-stack data engineering with Claude Code. I build the data pipeline. I do the analysis, frequently with LLMs for the text analysis part, and now increasingly with agents. I also build the front end in JavaScript. I&#8217;m not the best person you could hire for any one of these parts, but I&#8217;m good enough at all of them for various kinds of data projects. You can also put me in front of a client to take requirements, and I can brief or write up what I made.</p><p>What am I actually very good at? Architecting pipelines with LLMs. I&#8217;ve been doing it for<a href="https://presentofcoding.substack.com/p/named-entity-recognition-got-a-lot"> about as long as anyone has</a>. But I don&#8217;t want to only do that, and I don&#8217;t want to do it full-time on one specific pipeline.</p><p>My specialty is public, government data. If it&#8217;s in an API, on a website, or scattered across Excel files or PDFs, I&#8217;ll get it. And like with nearly all of the technical work, I&#8217;m an intermediate generalist: I&#8217;m not the best person to analyze any of the data sets I work with. The best people tend to be at the relevant federal agency, or building their own startups and consulting practices around the data, or they&#8217;re data SMEs who aren&#8217;t engineers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rT2p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rT2p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 424w, https://substackcdn.com/image/fetch/$s_!rT2p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 848w, https://substackcdn.com/image/fetch/$s_!rT2p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 1272w, https://substackcdn.com/image/fetch/$s_!rT2p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rT2p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png" width="1456" height="802" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:802,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rT2p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 424w, https://substackcdn.com/image/fetch/$s_!rT2p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 848w, https://substackcdn.com/image/fetch/$s_!rT2p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 1272w, https://substackcdn.com/image/fetch/$s_!rT2p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f176c0c-4c14-4086-9ef9-ee5d70a64f76_2048x1128.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">USAJobs is one of the data sets that I know better. This is one of my <a href="https://usajobs-historical.vercel.app/">bigger side projects</a></figcaption></figure></div><p>Having a brand like this is useful. It indicates where to focus my unpaid career-development time, like for side projects or talks. It tells me what to say yes to and how to describe myself. And it tells potential clients what not to hire me for: I&#8217;m not the right person for building software, because you can get someone cheaper and better at it, and I tell people that.</p><h2><strong>Marketing: none, or a lot</strong></h2><p>I got lucky early on with a client. We connected when I was on DRP. I offered to do something for free; they insisted on paying me for it, which was a good sign. They guarantee me up to 40 hours a week and they&#8217;re great to work with in a bunch of ways. I have one other substantial client, who I&#8217;ve been half-time with at various points, and then a handful of others I&#8217;ve done smaller projects for. I typically bill about 40 hours a week total, but the mix varies.</p><p>In a sense, I haven&#8217;t done any marketing to find clients. I haven&#8217;t posted on LinkedIn that I&#8217;m available. I mentioned a couple of times in talks that you can hire me, but no one ever did hire me out of that, so I stopped. The people I&#8217;ve worked for have been former coworkers or people in my network. A couple of times I&#8217;ve pitched a specific project to a specific group I thought would be interested, but I wouldn&#8217;t really describe that as marketing.</p><p>But the other way of looking at this is that I&#8217;m constantly marketing, in the sense that my life and work and hobbies have basically collapsed into the same thing: coding, writing, being in spaces where I meet people interested in the kinds of things I do, both online and in person. I&#8217;ve given four talks in the last three months. I co-organize a couple of meetups. I post far too much on LinkedIn. I have an upsetting number of coding side projects.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!v3KM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!v3KM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 424w, https://substackcdn.com/image/fetch/$s_!v3KM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 848w, https://substackcdn.com/image/fetch/$s_!v3KM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 1272w, https://substackcdn.com/image/fetch/$s_!v3KM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!v3KM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png" width="1456" height="1013" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1013,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!v3KM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 424w, https://substackcdn.com/image/fetch/$s_!v3KM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 848w, https://substackcdn.com/image/fetch/$s_!v3KM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 1272w, https://substackcdn.com/image/fetch/$s_!v3KM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72312b38-cce4-4425-a2cf-cb0cb0ae63f0_2046x1424.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Why do I have a UFO-document website? I think the better question is, why do you NOT have a UFO-document website?</em></figcaption></figure></div><p>What kinds of spaces am I in? Someone asked me recently what spaces were useful for networking, and I didn&#8217;t have a great answer. That&#8217;s because the best spaces are specific to your professional interests. They&#8217;re the ones that bring you into contact with people who might want to collaborate or hire you, or who you might want to hire. They&#8217;re probably not public, but public spaces are how you funnel into them. If you can&#8217;t find the space, it might not exist yet, and maybe you need to start it.</p><h2><strong>More on logistics</strong></h2><p>I file quarterly taxes. I registered my LLC and I got business insurance. I have a solo 401(k) that I fund from both the employer and employee side. I use Toggl to track hours by project, then enter them into whatever invoicing system the client uses.</p><p>Without staff, the administrative load isn&#8217;t that different from being a salaried employee. The biggest issue is budgeting for both sides of payroll taxes and retirement contributions.</p><p>The other big piece is that billing hourly makes the cost of every choice visible to me. Taking a break or going to a conference feels expensive because it displaces work I could be billing for. In some ways the difference from salaried work is illusory &#8212; I&#8217;ve had employers that paid out PTO, so there was still an hourly cost to taking time off, I just didn&#8217;t feel it as acutely. In other ways, there really is a difference: no one is going to subsidize my conference trips, and there&#8217;s work that in a salaried position would be part of the job, but now I have to choose between skipping it or eating the hours myself. For instance, a focus group on federal hiring is very much somewhere I want to be, but I&#8217;m also calculating the cost to attend and deciding if I can justify it to myself.</p><p>But the same mechanism that makes breaks feel expensive is what makes it possible to do work that wouldn&#8217;t fit in any salaried job. When <a href="https://data.opm.gov/">the new OPM data dropped early this year</a>, that was going to be a real chunk of my time for the next few days because I wanted to get to know it and to share that knowledge. I put together a call where I could go over it with some folks, in the middle of a work day, because I wanted to. No one was paying me for it, but that also meant I wasn&#8217;t using time that should have been an employer&#8217;s. I have trouble imagining anyone who would pay me for a salaried position and still let me do all of the side work I want to do at the times when I want to do it.</p><h2><strong>Always being on</strong></h2><p>There was a stretch at AI Corps, a few months, when I was spending most of my evenings and weekends not doing anything that looked like work. I was writing the occasional blog post, working on the occasional side project, but mostly I was hanging out with my kids, watching Netflix, or going to the gym. Then January 2025 came, I realized I was likely to need a new job pretty soon, and that was the end of my weekends. It&#8217;s been like that ever since.</p><p>The supposed benefit of not having a salaried position &#8212; that you can set your own hours &#8212; is true in a limited way. I&#8217;ll duck out some morning or afternoon most weeks. But I&#8217;m spending more hours on things that are like work than I think is healthy.</p><p>Some of that is fear. I&#8217;m afraid to let up, because everything with AI is moving fast and I&#8217;m afraid of being left behind. The fear isn&#8217;t about whether I can pay the mortgage this month. It&#8217;s about whether I&#8217;ll still be able to do this work in two years if I stop putting in the time to learn and build.</p><p>But a lot of it isn&#8217;t fear. I&#8217;m not responding on a Saturday afternoon to someone&#8217;s question about how to locate mid-level management in federal personnel data out of fear that if I don&#8217;t, I won&#8217;t be employable. I&#8217;m doing it because I want to. Claude Code is addictive. The work is interesting, and I also think it&#8217;s important that people be able to access and understand the data I work with. The talks and the side projects and the meetups and the Signal chats and the writing &#8212; I love doing all of it.</p><h2><strong>A year in</strong></h2><p>I feel extremely lucky that this is how my year has played out. A lot of people who left the federal government have <a href="https://www.linkedin.com/feed/update/urn:li:share:7437148475877883904/">struggled to replace their income or find anything comparable</a>. If you worked in international aid, there isn&#8217;t a big industry for that outside of government, and the jobs that do exist now have enormous competition.</p><p>My area of interest sort of went the other way. I started using Claude Code just before I left AI Corps, and that let me work at a speed and across a range of the tech stack that made what I do now possible. Interest in government data and LLM pipelines was also growing, and I sit at that intersection. I don&#8217;t think that would have helped me get a salaried job, because what people were hiring for just didn&#8217;t adjust that quickly, but it definitely helped me get paid work.</p><p>One of the things keeping me here is that I don&#8217;t want to be dependent on one institution the way I was at AI Corps. In a short amount of time, it went from being remote to in-person; the hours were now entirely set; the kinds of work we did and some of the tools we could use changed; and my professional development opportunities also became more limited. And that wasn&#8217;t unique to AI Corps. The same pattern keeps happening elsewhere: earlier this year, when DoD made the designation that Claude was <a href="https://www.anthropic.com/news/where-stand-department-war">a supply chain risk</a>, I was thinking about how if I had been in government and lucky enough to get Claude Code access, I would be freaking out at the prospect of the way I work being taken away. Having multiple clients means spreading risk: I don&#8217;t feel dependent or at anyone&#8217;s mercy the way I felt at DHS. It&#8217;s a real relief.</p><p>I also don&#8217;t know how I&#8217;d go back to a normal salaried role where you apply for a job and they compare you to a set of criteria. The longer I do this, the less legible I become. I don&#8217;t have a title, I don&#8217;t have a clear level of seniority, and the set of things I do every week doesn&#8217;t correspond well to any particular role that I&#8217;m aware of. And for now, that&#8217;s okay. I&#8217;m not trying to go back.</p><p>Some people make this kind of life look graceful. I make it look like I haven&#8217;t slept enough and my GitHub Actions just failed this morning and I don&#8217;t know why yet. But it&#8217;s mine, I chose it, and I&#8217;m so glad I get to do it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Should You Go Work for the Federal Government?]]></title><description><![CDATA[Not a pitch and not a warning]]></description><link>https://presentofcoding.substack.com/p/should-you-go-work-for-the-federal</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/should-you-go-work-for-the-federal</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 23 Feb 2026 13:02:59 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/184f467b-d3e6-469d-9000-3b4d7b8e3ec0_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When it comes to the topic of going to work for the federal government to do tech, I see two conversations happening. There are former civic tech people who are done &#8212; immensely skeptical of a government that treated them and their colleagues the way it did. I get that.</p><p>On the other side, there are the folks promoting these new hiring programs and talking up government tech modernization. They&#8217;re political appointees or others closely associated with the administration &#8212; not career civil servants. </p><p>Meanwhile, you're not hearing from the career folks who are still there, because they aren&#8217;t allowed to talk publicly about the challenges of the last year, why they've stayed, whether they're optimistic or not, or why they think you should join them.</p><p>What I have to say isn't as valuable as what you'd hear from them, but unlike them, I&#8217;m allowed to write what I want to.</p><p>This is a companion to <a href="https://presentofcoding.substack.com/p/the-government-is-hiring-tech-people">my previous post about the new federal tech hiring programs</a> &#8212; Tech Force, Data Science Fellows, and the rest. That piece was about what to look for if you apply to those specifically. This one is more general: how to think about whether to take a government job at all right now, particularly one in tech.</p><p>I don't know what the answer is for you, but here are the questions I think you should be asking.</p><h2><strong>Am I going to be asked to do something that goes against my values?</strong></h2><p>Maybe. It depends on the agency, the role, and your values.</p><p>For a lot of roles, the day-to-day is going to feel like any other large organization with a lot of bureaucracy. You&#8217;re modernizing a legacy system, building a pipeline, creating a dashboard.</p><p>But as part of that, you might be building tools for an agency whose broader mission or leadership you have problems with. You might be part of a narrative &#8212; &#8220;we&#8217;re finally modernizing government&#8221; &#8212; that you don&#8217;t think is accurate and is serving purposes you&#8217;re not comfortable with. The way you&#8217;re building might also go against your values &#8212; building in ways that aren&#8217;t accessible, don&#8217;t involve work with users, aren&#8217;t open-source, or just generally aren&#8217;t very good.</p><p>There are also other kinds of issues. How likely is it that your role will involve interacting with political leadership, and how comfortable is that going to be for you? Or, do you want to say &#8220;Department of War&#8221; all day long?</p><p>If you&#8217;re going into a senior role, there&#8217;s another version of this: you might think you&#8217;re going in to be a moderating influence, or to protect your team. That can be true. But your ability to steer things or protect people is likely going to be more limited than you think, and &#8220;they need me, it would be worse without me&#8221; can become a story you tell yourself while lending credibility to something you shouldn&#8217;t be lending credibility to.</p><p>Most of these aren&#8217;t entirely brand-new issues, but there are certainly teams and agencies where they&#8217;ve gotten worse during the last year.</p><p>But it's also true that if you care about the government working well, the most direct way to make that happen is to be inside, building. That's always been the case for government tech, and it hasn't stopped being true.</p><p><em>If you&#8217;re going into a role where something against your values is likely to come up, have some lines. Write them down, because once you&#8217;re in a role, it&#8217;s easy to justify whatever it takes to stay in it.</em></p><h2><strong>Am I going to be able to be effective?</strong></h2><p>The gap between &#8220;we&#8217;re modernizing government!&#8221; and shipping something useful is enormous.</p><p>Government tech has always had this problem. Someone announces a big initiative, there&#8217;s a launch event, maybe a blog post, and then it quietly dies two years later when the funding runs out or the champion leaves.</p><p>I don&#8217;t think this has improved. Overall capacity is significantly down. A lot of technologists either got pushed out or decided the circus wasn&#8217;t worth it and left on their own.</p><p>But things are still happening. There are teams that are doing important work and doing it well. I wish they would talk publicly more.</p><p>When you interview, ask what they&#8217;ve shipped recently. Ask what the dev environment looks like. Are people writing code, or managing contractors and writing reports? What&#8217;s the tech stack? If there&#8217;s code on GitHub for that agency, look at it.</p><p><em>Ask those questions, look at what they&#8217;ve built, and talk to people who are there or recently left, not just the ones trying to hire you.</em></p><h2><strong>Is this going to be an awful place to work?</strong></h2><p>Look, it might be.</p><p>Government tech was frequently depressing even in the best of times. </p><p>I&#8217;ve already written <a href="https://presentofcoding.substack.com/i/183460511/why-this-particular-moment-is-harder">the litany of things that happened last year</a>, and you&#8217;ve probably more or less heard it before anyway. It&#8217;s not over. A couple of people I know who made it through last year just had a terrible, demoralizing week because of actions reminiscent of the chaos of 2025. I can say that without worrying about getting them in trouble, because I&#8217;m sure that&#8217;s not uniquely identifying.</p><p><em>Some offices are still pretty insulated right now. Others went through a terrible stretch last year and have since settled down. Is that going to be stable? I don't know.</em></p><h2><strong>Is anyone going to want to hire me after I work for this government?</strong></h2><p>It&#8217;s true that &#8220;I worked for the federal government in 2026&#8221; may prompt a different set of questions in an interview than &#8220;I worked for the federal government in 2019&#8221; would have &#8212; but it depends what you&#8217;re doing. Going to work for ICE is going to look pretty different on a resume than going to work on FAFSA. The younger you are and the more briefly you&#8217;re there, the easier it will be to take it off your resume later on if it&#8217;s an issue. Seniority also matters: if you&#8217;re in a named leadership role, that&#8217;s googleable.</p><p><em>I don&#8217;t know the answer to this one &#8212; but if you&#8217;re doing something good and impactful and in line with your values, take the job and make your case later.</em></p><h2><strong>Am I going to get the career growth I want?</strong></h2><p>Government tech has always had a version of this problem &#8212; you can end up spending years on a tech stack or a way of building that just does not transfer to the private sector, or even to what more technical government jobs want. </p><p>For instance, right now in government very few engineers have access to the best AI coding tools&#8212;a lot of folks are using GitHub Copilot, which isn&#8217;t as good, and many have access to nothing.</p><p>This might or might not matter to you. My position&#8212;that I&#8217;d be reluctant to take a job where I can&#8217;t use <a href="https://presentofcoding.substack.com/p/hot-claude-summer">Claude Code</a>&#8212;is an extreme one: a lot of people would not put that anywhere near the top of their list of things to care about when evaluating a job. </p><p>Other considerations: whether there are people who can mentor you or who you can learn from technically, and whether you&#8217;re going to be hands-on building vs. managing contractors.</p><p><em>Think about your next best alternatives. Find out as much as you can about tooling and what your role involves.</em></p><h2><strong>Am I going to be asked to break the law?</strong></h2><p>In most roles, this is not going to be a major concern. But it&#8217;s something to think about. Here are a couple of ways it might come up:</p><p><strong>Talking about work off the record.</strong> Discussing substantive decisions &#8212; not coordinating carpool to a meeting &#8212; in Signal chats or other channels that aren&#8217;t FOIAable, and purposely not making them official records, violates the Federal Records Act. You could be disciplined for this.</p><p><strong>Data access.</strong> Accessing data you&#8217;re not supposed to have, or giving someone else access, can violate several laws. There&#8217;s a lot of litigation around data access and privacy right now &#8212; recent federal court action over improper sharing of confidential tax data, for instance. These cases typically target agencies and systems, not rank-and-file technologists. But even if you&#8217;re not a senior official, you can end up in court filings, IG reports, or public scrutiny if you mishandle data. This one is hard, because there&#8217;s not always a clear data owner or other point of contact to run this by. If you&#8217;re concerned, getting permission in writing on official systems is a good thing to do.</p><p>Other issues might come up too, but the advice is the same for all of it: get it in writing, on official systems. &#8220;My boss told me to do it verbally&#8221; is not a position you want to be in. &#8220;The agency general counsel told me in their official capacity that this was legal&#8221; is a much better one. But if you&#8217;re at the point where you need a formal legal opinion to feel okay about what you&#8217;re being asked to do, that&#8217;s a pretty bad sign.</p><p><em>This is going to be difficult to get a sense of before you join. But for most jobs, I would not worry about this. </em></p><h2><strong>Taking the job, leaving the job</strong></h2><p>For me, the answer is no &#8212; I&#8217;m not trying to go back. But some people I know and respect a great deal are still working in government, or want to return. And I&#8217;m glad for that. The government is doing things that matter regardless of your politics, and there are people still there trying to do them well.</p><p>You don&#8217;t need anyone&#8217;s permission to take a government job right now, and you don&#8217;t need anyone&#8217;s permission to leave if it stops being worth it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Please Switch to Python]]></title><description><![CDATA[Or R. Or Anything. Just Not Stata, SAS, SPSS, or MATLAB.]]></description><link>https://presentofcoding.substack.com/p/please-switch-to-python</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/please-switch-to-python</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Tue, 27 Jan 2026 13:02:37 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d7d14e98-57b8-4bba-a627-a501e2403e3e_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few weeks ago, <a href="https://data.opm.gov/">new federal workforce data</a> came out from OPM. There&#8217;s a drag-and-drop tool for pre-built visualizations, but they also made <a href="https://data.opm.gov/explore-data/data/data-downloads">over seven hundred monthly raw data files</a> available for download. How? You click the download button. One at a time.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>This is fine if you only want a few files. But I wanted hundreds of them, for myself and to make available for other people with questions about this data. Downloading them manually means leaving no record of what you did, and doing it all over again if the data updates from Version 1 to Version 2. And if you make a mistake, are you going to realize it?</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>I didn&#8217;t pull it manually, but I still got the data. I&#8217;ll explain how in a moment. But first, some context.</p><p>Stata, SAS, SPSS, and MATLAB are proprietary tools for statistical and mathematical analysis. You write code in them, though they have point-and-click interfaces as well. They&#8217;ve been around for decades, they&#8217;re taught in graduate programs, and a lot of people use them for analytical work.</p><p>When I say you should switch to Python from those tools, I&#8217;m using Python as a stand-in for something broader: open-source, general-purpose programming languages. R. JavaScript, whatever. The point here isn&#8217;t that Python is the One True Language<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. You might be able to do everything you need in R, or you might, as is increasingly common, combine several languages.</p><p>But Python is the biggest and most general-purpose of these languages and the one I use most, so that&#8217;s what I&#8217;ll focus on. The argument is really: join the world where tools work together, you can build anything you want, and you can share what you built. AI coding assistance is making it much easier: the switching costs fell, so there&#8217;s even less reason to stay where you are than there was a year ago.</p><h2>The OPM data</h2><p>The data got released on a Thursday. By the time I could look at it, I&#8217;d already done my full-time job, run a <a href="https://partiful.com/e/4QWVMV0tdaBOjRJclLuU">meetup</a>, and come home. I wanted to get this data up before the next morning, when I was hosting a call to share initial thoughts and go over what was available in the drag-and-drop tools vs. the raw data.</p><p>I also wanted to sleep.</p><p>Because of how the OPM site loads, to download the data automatically, I needed something that could control a web browser. There&#8217;s a Python library called <a href="https://playwright.dev/python/">Playwright</a> that does this beautifully. Anything you can do manually in Chrome, it can do with a script. A couple hours later, I had the files I needed, uploaded to <a href="https://huggingface.co/abigailhaddad">Hugging Face</a> where they can be easily downloaded or worked with in-place. I included a <a href="https://github.com/abigailhaddad/fedscope_new/blob/main/demo.ipynb">Jupyter notebook on GitHub</a> demonstrating how to pull from Hugging Face and analyze the data. <a href="https://presentofcoding.substack.com/p/hot-claude-summer">Claude Code</a> helped enormously with every step of this.</p><p>Besides just the data, what does this get me? A workflow that&#8217;s transparent: every step is shared on GitHub. It&#8217;s repeatable. Other people can run it. I can build on it: when new versions come out, I can tweak the code. If I wanted, I could set up a <a href="https://github.com/features/actions">GitHub Action</a> to check daily for updates automatically and upload them to Hugging Face.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FFjV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FFjV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 424w, https://substackcdn.com/image/fetch/$s_!FFjV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 848w, https://substackcdn.com/image/fetch/$s_!FFjV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 1272w, https://substackcdn.com/image/fetch/$s_!FFjV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FFjV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png" width="1456" height="885" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:885,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FFjV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 424w, https://substackcdn.com/image/fetch/$s_!FFjV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 848w, https://substackcdn.com/image/fetch/$s_!FFjV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 1272w, https://substackcdn.com/image/fetch/$s_!FFjV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6e8be0b-56e4-423c-88ab-7f1e7f57821a_1600x973.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This site of mine updates daily via GitHub Actions to pull new data from federal GitHub accounts.</figcaption></figure></div><p>Last week, a reporter flagged a possible issue in the data. I replicated it, built a <a href="https://github.com/abigailhaddad/fedscope_new/blob/main/reconciliation_analysis.ipynb">notebook</a> reproducing the issue, and sent a link to OPM. They can run it themselves, because <a href="https://colab.research.google.com/">Google Colab</a> makes that free for anyone. And they can follow what I did, because they have employees who know Python.</p><p>This is the infrastructure that exists. If you&#8217;re using Python.</p><h2>You can&#8217;t do that in Stata, SAS, SPSS, or MATLAB</h2><p>Browser automation? Stata can&#8217;t. SAS can&#8217;t. SPSS can&#8217;t. MATLAB&#8217;s answer is &#8220;<a href="https://www.mathworks.com/help/matlab/call-python-libraries.html">call Python from MATLAB</a>.&#8221;</p><p>Upload the data to Hugging Face? You&#8217;re going to be stuck using the GUI to drag-and-drop it.</p><p>Create a notebook anyone can run for free online? None of these allow that.</p><p>Put it on GitHub Actions to run automatically? Python comes pre-installed on GitHub Actions and can be run for free. None of these proprietary tools have that.</p><p>The pattern: even where these tools have some capability, it requires calling Python, or expensive licenses, or both. You only get the tools someone built for you&#8212;and those are narrower, because you&#8217;re a smaller and more specialized group.</p><h2>What else opens up</h2><p>Once you&#8217;re in Python, what counts as &#8220;data&#8221; expands dramatically.</p><p>Data no longer has to be a CSV or an API call wrapped up in a nice bow. It can be PDFs you found by automating Google searches. It can be Excel files someone built intending them to be gone through by hand, but you want years of them, you want to process their different formats and tabs, and you want a pipeline that grabs new ones and alerts you if they don&#8217;t match what you&#8217;re expecting.</p><p><strong>Anything you can access online can be data, if you want it hard enough.</strong></p><p>And then there&#8217;s what you can build to show your findings. I work in JavaScript now, and there are still plenty of websites I wouldn&#8217;t trust myself to build yet: anything with user authentication, a back end, payments. But if you&#8217;re a data person who wants sites with interactive visualizations? The JavaScript <a href="https://d3js.org/">D3 library</a> is what <a href="https://www.nytimes.com/spotlight/graphics">data journalists</a> and <a href="https://pudding.cool/">data storytellers</a> use. It&#8217;s the gold standard for communicating your results and letting other people play with your model or your findings.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-mg8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-mg8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 424w, https://substackcdn.com/image/fetch/$s_!-mg8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 848w, https://substackcdn.com/image/fetch/$s_!-mg8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 1272w, https://substackcdn.com/image/fetch/$s_!-mg8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-mg8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png" width="532" height="420.90588235294115" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1076,&quot;width&quot;:1360,&quot;resizeWidth&quot;:532,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-mg8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 424w, https://substackcdn.com/image/fetch/$s_!-mg8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 848w, https://substackcdn.com/image/fetch/$s_!-mg8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 1272w, https://substackcdn.com/image/fetch/$s_!-mg8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f1aa3d4-e4e7-47d1-bc41-651beb9342a4_1360x1076.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is a heat map from the New York Times using the new OPM data. You could get something this nice-looking with <a href="https://posit-dev.github.io/great-tables/articles/intro.html">Python&#8217;s great-tables package</a>, but interactive web visualizations like this are typically built in JavaScript.</figcaption></figure></div><p>And the sharing infrastructure isn&#8217;t just about code or results. It&#8217;s about data too. Hugging Face, <a href="https://git-lfs.com/">git large file storage</a>, all the tools software developers have been building let you easily share data. If your tools include Python, there&#8217;s a whole data-sharing ecosystem.</p><h2>&#8220;I have no obligation to believe anything they write&#8221;</h2><p>Researcher and statistician Andrew Gelman has this line I think about a lot: <a href="https://statmodeling.stat.columbia.edu/2023/09/10/the-authors-of-research-papers-have-no-obligation-to-share-their-data-and-code-and-i-have-no-obligation-to-believe-anything-they-write/">&#8220;The authors of research papers have no obligation to share their data and code, and I have no obligation to believe anything they write.&#8221;</a></p><p>This is how I feel about anyone trying to persuade the public of something while coding in languages that aren&#8217;t free to run. Are there people using Python who also don&#8217;t share their code? Sure, and that&#8217;s bad too. But if you&#8217;re using a proprietary language, you can&#8217;t share in a useful way even if you want to.</p><p>Part of this is audience. If you share a Stata .do file, only people with Stata licenses can run it. If you&#8217;re okay limiting yourself to the subset of your field who have licenses and know how to use them, fine. But if you want your work accessible to journalists, policymakers, researchers in adjacent fields, the public&#8212;you need tools they can use.</p><p>And part of it is structural. Users of proprietary statistical software are far less likely to share code at all because the tools don&#8217;t encourage it. Your code probably isn&#8217;t in a Git repo. It&#8217;s less likely to run end-to-end without manual steps. The workflow of &#8220;write reproducible code, put it on GitHub, let anyone run it&#8221; isn&#8217;t what these ecosystems were built for. Python and R communities developed around reproducibility and sharing. The proprietary tools didn't, so reproducibility in those ecosystems is the exception, not the norm.</p><p>Even if your code should never be public, the same problems apply internally: you can't run each other's work without licenses, can't easily hand it off, can't do anything outside this ecosystem.</p><h2>The exceptions</h2><p>Are there things you genuinely can&#8217;t do outside your proprietary software? Yes, but the list is short. SAS is still dominant for pharmaceutical submissions to the FDA, although there&#8217;s a growing R community.  MATLAB's Simulink has capabilities for control systems hardware deployment that Python can't match. But Python now has <a href="https://pypi.org/project/PuLP/">PuLP</a> for linear and integer programming, and <a href="https://pytorch.org/">PyTorch</a> for machine learning&#8212;and Python has become the standard in ML.</p><p>And if you&#8217;re an economist cleaning data and running regressions, or even doing more complex statistical work<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>? You&#8217;re probably using it because you learned it in grad school and switching felt hard. Well, it&#8217;s not hard anymore. You can install Claude Code and ask it to translate your .do file into Python, run it, and compare the results. I&#8217;ve done this. If you can do the statistical analysis, you can figure out the migration as well.</p><p>And even where regulators demand a specific tool, or your analysis needs something not yet built in R or Python, you still benefit from using those languages. I used to work on a team where we had to use ACL, another proprietary analysis software, for compliance purposes: the auditors wanted the logs. So I wrote Python that generated the ACL code and ran both workflows in parallel, comparing results. Back then I didn&#8217;t know how to automate that comparison or have Python kick off the ACL, but now I do. The specialized tool can be the last mile, not the whole journey.</p><h2>There&#8217;s a whole world out there</h2><p>I know coders who prefer R but work in Python because that&#8217;s what the market asks them to do. I&#8217;ve rarely met anyone who learned Python or R after switching from Stata or SAS and said, &#8220;I wish I were still working in those.&#8221; Not everyone gets to choose their tools, but if you want to move to a job outside this ecosystem someday, or if you want to help your organization do better work, you need to know what else is out there.</p><p>There&#8217;s a learning curve, but it&#8217;s way less than it used to be. I haven&#8217;t written a line of code myself in months&#8212;Claude Code does it. The AI coding assistants are good enough now that &#8220;learning Python&#8221; increasingly means learning to think about architecture and workflows: how do you want data to flow, what should update automatically, how should pieces connect, what should you test? You no longer need to master syntax to work in these ecosystems.</p><p>And when you get there, I think you&#8217;ll like it. There&#8217;s data you haven&#8217;t been able to touch because it doesn&#8217;t come in a nice CSV. There are visualizations you haven&#8217;t been able to build because your tools don&#8217;t do interactive. There&#8217;s an entire infrastructure for sharing your work and your data that you&#8217;re not part of. <a href="https://www.jetbrains.com/lp/devecosystem-2024/">Half of all developers use Python.</a> Tens of millions of people, building tools for each other, for decades.</p><p>But maybe you&#8217;re reading this thinking: I don&#8217;t need browser automation. I don&#8217;t care about Hugging Face. I&#8217;m not trying to share anything with the public and I never want to make a website. Fine. But do you ever struggle to remember what you did six months ago? Do you have a 1,500-line .do file you&#8217;re afraid to touch? Do you copy-paste the same code between projects? Do you dread handing off work to a coauthor? Do you redo the same manual steps every time new data comes in?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Nqfl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Nqfl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 424w, https://substackcdn.com/image/fetch/$s_!Nqfl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 848w, https://substackcdn.com/image/fetch/$s_!Nqfl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 1272w, https://substackcdn.com/image/fetch/$s_!Nqfl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Nqfl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png" width="1456" height="666" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:666,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Nqfl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 424w, https://substackcdn.com/image/fetch/$s_!Nqfl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 848w, https://substackcdn.com/image/fetch/$s_!Nqfl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 1272w, https://substackcdn.com/image/fetch/$s_!Nqfl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa53dfaf4-5c96-4682-a751-23d50ae24609_1600x732.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Stata licenses also limit how much of your own hardware you can use to run their software. The maximum number of variables, observations, and speed is dictated not just by your own memory but by how much you pay for a license. Guys, this isn&#8217;t normal or okay.</figcaption></figure></div><p>General-purpose programming languages solve these problems too. Functions you can abstract out and reuse. Version control that tracks every change. Package managers that handle dependencies. The big flashy stuff&#8212;the browser automation, the sharing infrastructure&#8212;is what I&#8217;ve been talking about because it&#8217;s cool. But the boring stuff matters too, and it&#8217;s also better in Python.</p><h1>The moat is disappearing</h1><p>Unless you control access to unique data, the barriers to entry for analysis in your field have fallen. A grad student or policy analyst or random blogger with Claude Code can use your work and spin up something real with the same data you&#8217;re using, without being limited by their tools. And they can also access other data that you&#8217;re not able to.</p><p>The world where you can build a full pipeline in a weekend, pull from multiple datasets, test it, and share everything openly is here. The people who are excited about what&#8217;s becoming possible aren&#8217;t waiting.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>This is not a complaint; I agree with the focus on drag-and-drop tools for the first iteration of the site.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>If you hate Python but love Rust or Julia or C++ or lisp, I love you anyway and you&#8217;re not who I&#8217;m talking to and you can write your own blog post.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>For instance, <a href="https://www.pymc.io/welcome.html">PyMC</a> for Bayesian modeling, <a href="https://lifelines.readthedocs.io/en/latest/Survival%20Analysis%20intro.html">lifelines</a> for survival analysis, and the R <a href="https://cran.r-project.org/web/packages/did/vignettes/did-basics.html">did</a> package for difference-in-differences. </p></div></div>]]></content:encoded></item><item><title><![CDATA[Vibe Coding Websites]]></title><description><![CDATA[So Developers Don't Curse You Later]]></description><link>https://presentofcoding.substack.com/p/so-youre-vibe-coding-a-website</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/so-youre-vibe-coding-a-website</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Thu, 22 Jan 2026 13:03:08 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/710090a2-5a6f-4a3b-9855-fc6ba0dd0637_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Shortly after I deployed my first website with Claude Code last May, I was on a call showing a software developer what I&#8217;d built. When I explained my deployment process&#8212;dragging and dropping a folder into Netlify&#8212;I could see him trying to figure out how to say &#8220;what the fuck are you doing&#8221; politely.</p><p>My background is Python and data science, not front end. If you ask me how to explore a dataset or pick a good visualization, I'll give you some curse-of-knowledge answer that's useless to a beginner. But I've only been building websites with Claude Code for eight months, so there&#8217;s definitely no curse of knowledge here. Through trial and error (and suggestions), this is where I've landed and why in terms of technical practices. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h1><strong>What I&#8217;m Building and How</strong></h1><p>These tips are somewhat specific to what I build, which is data pipelines with static JavaScript front ends.</p><p>A static site is a site with no back end&#8212;no server running code, no database being pulled from. It&#8217;s just HTML, CSS, and JavaScript files sitting somewhere. When a user visits your site, their browser downloads those files and runs the JavaScript locally. Everything happens in that browser.</p><p>For almost all of these, I also have a Python pipeline that processes data and outputs data files. The pipeline runs on my computer (or, as the project matures, on a schedule via <a href="https://presentofcoding.substack.com/i/177523827/github-actions">GitHub Actions</a>), regenerates the file with new data, and pushes the updated data to GitHub. From there, <a href="https://presentofcoding.substack.com/i/177523827/netlify">Netlify</a>&#8212;a service that hosts static sites for free&#8212;automatically deploys it.</p><p>If instead you&#8217;re building a website with user accounts and a database, this still applies, but you&#8217;ve got a lot more to worry about on top of that.</p><h2><strong>Put It on the Internet&#8211;Continuously</strong></h2><p>Don't be me eight months ago, dragging and dropping folders. Set up Netlify to do continuous deployment from GitHub: you push code and data to GitHub, and Netlify automatically rebuilds and deploys the site.</p><p>This matters because deployment should be easy, boring, and automatic.</p><p>Netlify has a generous free tier. Your site might fail to build at first, but each time after that will be easier.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e-Uz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e-Uz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 424w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 848w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1272w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png" width="1316" height="484" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:484,&quot;width&quot;:1316,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e-Uz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 424w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 848w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1272w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Netlify has a free tier for deploying websites</figcaption></figure></div><h2><strong>Use Someone Else&#8217;s Components</strong></h2><p>Don't build things from scratch when you can use someone else's code. Look for libraries&#8212;pre-built tools you can drop into your project. Periodically ask Claude: "Is there a library for this?" Otherwise, the AI will happily write you 200 lines of custom code when a library does it in five.</p><p>Here are a few that I like:</p><ol><li><p><strong><a href="https://datatables.net/">DataTables</a>:</strong> For tables with sorting, filtering, search, and CSV export. And make sure you&#8217;re actually using it for everything: I was spending half my time on the front end just on filters&#8212;getting Claude to write custom filter code, realizing the filter code didn&#8217;t actually work, debugging filter code. Now, as much as possible, I use the filtering native to DataTables. </p></li><li><p><strong>D3:</strong> If you want interactive data visualization that looks like what data journalists and <a href="https://pudding.cool/2024/07/sleep-training/">other data viz pros</a> use, you want D3. I tried to build a bubble chart in Python&#8212;where the size of each bubble represents a value&#8212;and it just wasn&#8217;t happening for me. The Python visualization libraries are great for static charts, but for anything interactive, I&#8217;m fighting them the whole way on appearance. With D3, I had a working interactive bubble chart in an evening. Yes, there are wrappers for D3 in other languages, but if you&#8217;re using tools like Claude Code anyway, you can just use D3 directly.</p></li><li><p><strong><a href="https://getbootstrap.com/">Bootstrap</a>:</strong> For layout and basic visual stuff&#8212;buttons, cards, forms, making things look reasonable on mobile. Full disclosure: I&#8217;ve only used this twice, but I was able to delete hundreds of lines of CSS without making my sites look or operate worse.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mA85!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mA85!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 424w, https://substackcdn.com/image/fetch/$s_!mA85!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 848w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1272w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mA85!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png" width="1456" height="528" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:528,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mA85!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 424w, https://substackcdn.com/image/fetch/$s_!mA85!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 848w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1272w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is a bubble chart in D3</figcaption></figure></div><h2><strong>Put Your Colors and Sizes in One Place</strong></h2><p>CSS&#8212;Cascading Style Sheets&#8212;is how you control what your website looks like. It&#8217;s separate from HTML, which is the structure and content. CSS handles colors, fonts, spacing, layout.</p><p>CSS lets you define variables&#8212;values you name once and use everywhere. When the color scheme changes, you change a few lines in one file instead of hunting through your whole repository.</p><p>I keep styles that show up on every page (tables, buttons, popup boxes) in a separate CSS file. Styles that are unique to one page can live directly in that page&#8217;s HTML.</p><p>Customizing your CSS is also how you stop your site from looking like every other AI-generated page, if that&#8217;s something you want.</p><h1>Test Your Website</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YQHp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YQHp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 424w, https://substackcdn.com/image/fetch/$s_!YQHp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 848w, https://substackcdn.com/image/fetch/$s_!YQHp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 1272w, https://substackcdn.com/image/fetch/$s_!YQHp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YQHp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png" width="1036" height="342" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:342,&quot;width&quot;:1036,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:43587,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/185254755?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YQHp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 424w, https://substackcdn.com/image/fetch/$s_!YQHp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 848w, https://substackcdn.com/image/fetch/$s_!YQHp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 1272w, https://substackcdn.com/image/fetch/$s_!YQHp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61dd77e4-21ac-46f9-a45e-c8c50124dd5c_1036x342.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">It&#8217;s nice when tests pass. It&#8217;s also nice when they fail and tell you they failed.</figcaption></figure></div><p>I test my sites now because I shipped broken stuff and didn&#8217;t notice until later.</p><p>There are two kinds of tests I use: data tests and front end tests. Data tests make sure the data is in the format I need and I didn&#8217;t drop any of it since the last time the pipeline ran.</p><p>I initially didn&#8217;t write front end tests, but they turned out to be easier than I thought, so now I do.</p><p>Four categories of front end tests catch most of my &#8220;it broke and I didn&#8217;t notice&#8221; problems:</p><ol><li><p><strong>Page loads without error.</strong> Catches broken imports, missing files.</p></li><li><p><strong>Data loads.</strong> Makes sure the table isn&#8217;t empty.</p></li><li><p><strong>Search/filters change results.</strong> Your search box looks nice, but does typing in it do anything? This catches when the user interface exists but isn&#8217;t connected to the data.</p></li><li><p><strong>Search finds something you know exists.</strong> If your state filter has &#8220;Illinois&#8221; and your data has &#8220;IL&#8221;, you&#8217;ll get zero results. A test catches that mismatch.</p></li></ol><p>You can run these as part of your GitHub Actions deployment setup: that is, GitHub can run both your data and your front end tests and <a href="https://presentofcoding.substack.com/i/177523827/multiple-branches">only deploy to Netlify</a> if they all pass. </p><p>For front-end tests, you'll need a headless browser. I use Playwright. It loads your page, clicks buttons, types in search boxes, and checks for expected behavior. And Claude Code is good at writing these tests if you describe what behavior you want to verify; I use it with the <a href="https://github.com/microsoft/playwright-mcp">Playwright MCP Server.</a> </p><h1><strong>Make Things Shareable via URL</strong></h1><p>This is more specific, but it&#8217;s a nice pattern that I&#8217;m using now and I really like.</p><p>You can put user selections into the URL, like yoursite.com/data?year=2024. Now that view is shareable. Someone can bookmark it. They can send the link to a colleague. Whereas if you store state only in the browser&#8217;s memory, it can&#8217;t be shared.</p><h1><strong>If You&#8217;re Coming from Python</strong></h1><p>I was brand-new to JavaScript, but I wasn&#8217;t new to coding, and so there were also some patterns I was able to bring over that were useful.</p><p><strong>Don&#8217;t repeat yourself</strong> applies here too. If you&#8217;re writing the same code in multiple places, pull it into a function or a separate file.</p><p><strong>Config files are nice.</strong> You can have a config.json that defines things like which fields to show or what the column headers should be. That way when those change, you change the config, not the code.</p><p><strong>Keep your data separate from your display.</strong> Your data lives in a JSON file, not embedded in the HTML. When your pipeline regenerates the JSON, you don&#8217;t have to touch the website code.</p><h1><strong>Why This Matters (Or Doesn&#8217;t)</strong></h1><p>If you&#8217;re building a one-time site for fun that you&#8217;ll never touch again, most of this doesn&#8217;t matter. Ship it, move on.</p><p>But if you're planning to keep building on something&#8212;adding features, updating data, fixing bugs&#8212;there's a concept worth knowing: technical debt. Technical debt is what happens when you say "I'll fix this later" forty times and then, suddenly, it's later. It's the code you copied and pasted instead of abstracting into a function, so now you have to change it in multiple places. It's the CSS scattered across various files, so you can't find where that shade of blue is coming from. It's the deployment process that requires you to remember various manual steps including commenting out your code. </p><p>Technical debt isn&#8217;t always bad. Sometimes you take on debt intentionally because you need to ship fast. But the messier your code base gets, the harder every additional change becomes.</p><p>Everything in this post is about minimizing technical debt:</p><ul><li><p><strong>Using libraries</strong> means less code you wrote and have to maintain.</p></li><li><p><strong>Abstracting shared code</strong> means changing code in one place when you need to fix something.</p></li><li><p><strong>CSS variables</strong> mean updating colors once.</p></li><li><p><strong>Tests</strong> mean catching bugs before you deploy.</p></li><li><p><strong>Continuous deployment</strong> means not forgetting to push updates&#8212;and having a process that runs those tests before deployment.</p></li></ul><p>Every line you write is a line you might have to debug later. The goal isn&#8217;t writing a lot of code&#8212;it&#8217;s writing as little as possible to do what you want.</p><p>I&#8217;m having fun building these sites, and I want to keep having fun. Technical debt is the opposite of fun.</p><p>And if you ever hand your project over to a developer, you want it to be a good transition&#8212;not one where they&#8217;re cursing you and your vibe coding.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The Government is Hiring Tech People Again]]></title><description><![CDATA[Should you apply?]]></description><link>https://presentofcoding.substack.com/p/the-government-is-hiring-tech-people</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/the-government-is-hiring-tech-people</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 05 Jan 2026 13:03:44 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ceb3bb02-a67a-4a0e-80d2-b2641932a67b_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>My first stint as a government data scientist went to some places that, at the time, I would have described as &#8216;dramatic.&#8217;</p><p>For instance: a coworker at the same level as me emailed me an org chart showing that I now reported to her. She told me I couldn&#8217;t share it with anyone. Naturally, I did. Turns out I did not, in fact, report to her.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>But the drama wasn&#8217;t even the biggest issue. The real problem&#8212;and this has been the case for every technical job I&#8217;ve done in government&#8212;was figuring out, between me and management, how to identify projects that were appropriate for my skill set, possible to do given our team&#8217;s technical and personnel constraints, and useful to my agency.</p><p>On paper, this should be simple: there are technical problems, you bring in people with the skills to solve them, voila. In practice, it&#8217;s not. Which is how I&#8217;ve found myself, at various points, wrangling spreadsheets instead of coding, managing contractors, and building models that were never going to get used.</p><p>At my most recent civil service job at the short-lived <a href="https://www.dhs.gov/archive/news/2024/10/30/fact-sheet-dhs-completes-first-phase-ai-technology-pilots-hires-new-ai-corps">AI Corps at the Department of Homeland Security</a>, this was done well&#8212;but I didn&#8217;t realize at the time how much work was happening behind the scenes to enable that. We had leadership with previous experience with digital services teams in government, which meant we had a significant advantage in doing it right. And it was still a challenge.</p><p>And that was before everything went sideways.</p><h1><strong>What Happened Last Year</strong></h1><p><a href="https://federalnewsnetwork.com/workforce/2025/11/317000-feds-have-left-the-government-this-year-surpassing-opms-goal/">The federal government ended 2025 down roughly 250,000 people</a>. Technical folks were not excluded from that number. <a href="https://www.nextgov.com/people/2025/03/gsa-eliminates-18f/403400/">18F got dismantled</a>&#8212;that was the team that built tools like cloud.gov. The U.S. Digital Service (USDS) got taken over by DOGE, fired some people, and saw <a href="https://fedscoop.com/usds-workers-quit-doge-tech-elon-musk/">significant resignations</a>. Some agencies conducted terminations of probationary employees&#8212;anyone hired or promoted in the past year or two.</p><p>At Homeland Security, some engineers were <a href="https://federalnewsnetwork.com/workforce-rightsgovernance/2025/05/fired-dhs-probationary-employees-granted-class-certification-in-mspb-appeal/">fired for being probationary</a>. More left semi-voluntarily, through a combination of early retirement and buyouts as the carrot, and return to office (including for employees hired to be fully remote, which included everyone on AI Corps), forced reassignments requiring relocation, and a fear of additional layoffs as the stick.</p><p>I loved the work at <a href="https://www.dhs.gov/archive/news/2024/06/25/dhs-hires-first-10-experts-ai-corps-recruiting-sprint">AI Corps</a>. Then the chaos started. Projects stopped. We were told by leadership that there weren&#8217;t plans to eliminate our team, but also that individuals likely would be fired&#8212;and the indications were all negative that things would be functional again.</p><p>And then came the <a href="https://www.govexec.com/workforce/2025/04/some-dhs-employees-told-send-selfies-prove-they-are-office-department-suddenly-ends-remote-work/404893/">Sunday afternoon email</a> ordering us to report back to work five days a week or be fired starting the next morning.</p><p>I left shortly after that.</p><h1><strong>And Now They&#8217;re Hiring Again</strong></h1><p>Last month, the Office of Personnel Management (OPM) <a href="https://www.opm.gov/news/news-releases/opm-launches-us-tech-force-to-implement-president-trumps-vision-for-technology-leadership/">announced several new programs</a>: U.S. Tech Force (1,000 fellows annually), Data Science Fellows (250), and Project Management Fellows (250). These are all short-term roles where OPM assists with the hiring, but actual assignments are to various agencies across the executive branch.</p><p>The goal? &#8220;Modernize the federal government&#8221; and &#8220;tackle the government&#8217;s most complex and large-scale challenges.&#8221;</p><p>These are good goals. If you want to work on them, I hope you find a role where you can do that. And I also hope these programs are successful.</p><p>But they might not be. So if you&#8217;re going to apply, go in with your eyes open about what to look for.</p><h1><strong>Why This Work Is Hard (Even in Good Times)</strong></h1><p>Government tech modernization is difficult. OPM spent approximately <a href="https://www.gao.gov/products/gao-12-226t">$290 million</a> on a project to automate federal employee retirement claims before <a href="https://federalnewsnetwork.com/workforce/2011/04/opm-filling-holes-left-by-retirement-system-failure/">canceling it in 2011</a>. The Coast Guard spent <a href="https://www.gao.gov/products/gao-18-59">$67 million over five years</a> trying to replace its aging health records system before scrapping the effort; <a href="https://spectrum.ieee.org/us-coast-guards-67-million-ehr-fiasco">as of 2018 it was still paper-based</a>. The VA spent <a href="https://www.gao.gov/products/gao-10-579">$127 million over nine years</a> on a<a href="https://docs.house.gov/meetings/VR/VR11/20190926/109990/HHRG-116-VR11-Wstate-ReinkemeyerL-20190926.pdf"> scheduling system that never launched</a>. The FAA&#8217;s air traffic control systems include <a href="https://www.gao.gov/products/gao-24-107001">multiple systems over 30 years old</a>; its ongoing modernization effort, NextGen, has faced <a href="https://www.gao.gov/products/gao-25-108162">decades of delays</a>, and some critical systems won&#8217;t be modernized until 2035.</p><p>I think of the core problem as responsibility without authority.</p><p>For instance, it&#8217;s your job to modernize the agency&#8217;s data systems. But you&#8217;re reliant on contractors to do much of the work because you&#8217;re not staffed to build everything the agency wants fixed by yourselves. The contracts have already been competed and awarded, most likely to the vendor putting forth the <a href="https://hhunt56.substack.com/p/lowest-priced-technically-acceptable">Lowest Priced Technically Acceptable</a> proposal, not the best. The payment structure also likely incentivizes billing hours rather than building good products.</p><p>Additionally, the roles and skill sets the contractors were hired for may not be the ones you need and the work may not be scoped in a way that&#8217;s useful to you. And if it&#8217;s not working out, you can&#8217;t just change the contract or bring in different people. That takes months or years, if you can do it at all. (And you probably can&#8217;t, because you don&#8217;t know how and your office doesn&#8217;t even own the contracts.) And good luck if you try to get involved in pushing the contractor to hire or screen differently.</p><p>Or maybe the contract is fine, but you need existing code from the previous contractor or else you&#8217;re way behind. Where does the code live? Not on any server you&#8217;re going to get access to, because whoever was managing that previous contract never asked for it.</p><p>You also can&#8217;t change hiring regulations for civil servants. You may not even be able to get HR to do things that are totally legal.</p><p>And then there&#8217;s risk aversion about the wrong things. A lot of people are terrified of a process violation, of something that could look bad in an audit. But they&#8217;re not as worried about the system being terrible and not working for users, or wasting years and millions of dollars on something that doesn&#8217;t solve the problem.</p><p>Meanwhile, your leadership is under pressure for short-term wins. They just brought in a bunch of expensive, highly visible staff. They need to show results. But they may not know where the opportunities to be effective are&#8212;what&#8217;s realistic to accomplish, what would require years of groundwork, what&#8217;s blocked by forces outside their control, like Congress. They may want innovation but settle for innovation theater.</p><p>Finally, a lot of people at the agency you work in and whose assistance you need are predisposed to dislike you. You&#8217;re likely younger, you&#8217;re paid more, and your mission (to fix the bad stuff) is an implicit criticism of them. I&#8217;m not saying everyone sees it that way, but &#8220;they thought they were the smartest people in the room and they didn&#8217;t listen to us&#8221; is something that gets said so regularly about digital services teams in government that it&#8217;s hard to tell when it&#8217;s true and when it&#8217;s not<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>.</p><p>The limitation on making progress in government is rarely engineering skills. Building the thing is usually the easiest part. It&#8217;s everything else that&#8217;s hard.</p><p>And all of that is just the starting point, in a good year<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>.</p><h1><strong>Why This Particular Moment Is Harder</strong></h1><p>Think about the year civil servants&#8212;the people you will be working with and need buy-in from<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>, should you do any of these programs&#8212;just completed.</p><p>Russell Vought, who ran the Office of Management and Budget in Trump&#8217;s first term, said in a private 2023 speech that in a second Trump administration, &#8220;We want the bureaucrats to be traumatically affected. When they wake up in the morning, we want them to not want to go to work because they are increasingly viewed as the villains.&#8221;</p><p>&#8220;<a href="https://www.eenews.net/articles/russ-vought-wanted-feds-in-trauma-its-happening/">We want to put them in trauma</a>,&#8221; he said.</p><p>And that&#8217;s pretty much what happened in 2025. People were told with no notice to return <a href="https://www.ksbw.com/article/federal-workers-return-offices-without-desks-wi-fi-lights/64036609">to offices with no space for them</a>. Folks you&#8217;d helped recruit and persuade to join the government were fired, or left because they had good reason to think they would be. Staff were <a href="https://fedscoop.com/usds-workers-quit-doge-tech-elon-musk/">called into meetings with DOGE representatives</a> who wouldn&#8217;t turn their cameras on and asked to justify their jobs and offer judgment on their coworkers. <a href="https://www.dailywire.com/news/a-doge-origin-story-how-barack-obama-laid-the-groundwork-for-elon-musk">Hit pieces were written calling out specific employees</a> in ways that appeared coordinated with the people making personnel cuts.</p><p>And all of that was just a small subset of the things that happened to people I know personally.</p><p>So when you show up as a new Tech Force fellow, there&#8217;s going to be additional skepticism besides just the normal kind. People just watched their colleagues with a lot more experience in your fields get pushed out or fired. And here you come, early career, only here for a short time, and hired to do...what exactly?</p><p>Also, it's not as if everything has settled down: you'll either be subject to ongoing actions or you'll be insulated from them. Either is a problem.</p><p>And there&#8217;s another layer of instability: contract actions. Last year saw widespread <a href="https://www.govexec.com/workforce/2025/11/shutdown-compounds-year-pain-federal-contractors-employees/409304/">cancellations of federal contracts</a> and delays in awards and extensions. At Homeland Security, <a href="https://www.pogo.org/investigates/99-999-dhs-contracts-balloon-under-kristi-noems-directive">contract actions of $100,000 or above still require sign-off from the Secretary</a>. You will not be directly affected, but the contractors you work side-by-side with and depend on? They may be.</p><p>Finally, if the starting assumption from the agency leadership that brought you in&#8212;and potentially even from your managers brought in from industry to manage you&#8212;is that the government doesn&#8217;t work because civil servants are stupid or lazy, you&#8217;re starting from a terrible position. You need to build trust with people to get things done. That&#8217;s hard when the message from above is contempt and when you&#8217;re under pressure to put out a narrative, both in the agency and externally, that minimizes the contributions of career civil servants.</p><p>Here&#8217;s what to look for when you apply to reduce the likelihood that you&#8217;re walking into a situation like that.</p><h1><strong>What to Look for If You Apply</strong></h1><p>When you&#8217;re interviewing, look to see that someone running this program at your agency has an actual theory of change about building things in government and a history of successfully doing so. Get names and find out what their backgrounds are.</p><p>Ask questions like:</p><ul><li><p>What conversations have happened with agency leadership? How have they prepared for us?</p></li><li><p>Have projects been scoped yet? What does that process look like?</p></li><li><p>Regarding those projects, what&#8217;s been tried before at this agency and what are we doing differently? Who is currently working on them and how are we going to work with them?</p></li><li><p>What infrastructure exists for us? Is there a git server? Are we going to be allowed to use AI coding tools, and if so, what?</p></li></ul><ul><li><p>What&#8217;s the process for user research? Are we hiring or working with UX researchers or designers? How will we talk to the people who use these systems?</p></li></ul><p><strong>Do not just assume this has been figured out.</strong> I&#8217;m looking at OPM&#8217;s long list of participating agencies and I would be surprised if when that was released, they&#8217;d had extensive conversations with each one to assess that they&#8217;re going to make productive use of you.</p><p>I&#8217;m sure agency leadership said &#8220;by all means, send us technical people&#8221;, but did it go beyond that, or will it before they start hiring? And if the agencies don&#8217;t have good plans, will OPM back down from their very ambitious, very public hiring goals?</p><p>Normally, this could get deferred slightly, and they could work things out after you show up. But these are one and two-year terms. If there aren&#8217;t projects scoped by the time you get there, you could easily burn through a big chunk of your term waiting for something useful to do&#8212;or discover that the people you&#8217;re working for don&#8217;t know how to find that.</p><p>My prediction: Experiences will vary wildly agency to agency. Some agencies will do this well and others will not.</p><h1><strong>What You&#8217;re Signing Up For</strong></h1><p>A lot of tech within the federal government is bad, and the challenges to improvement aren&#8217;t inherently insurmountable. Even last year, good things were built.</p><p>And I don&#8217;t think the premise or structure of these programs is wrong. Centralized hiring is absolutely the way to go, because getting hiring announcements out and screening resumes is a huge lift that most agencies don&#8217;t have the capacity to do. (Does OPM? They can staff up to do it, and it&#8217;s easier to solve this for one agency than for all of them.)</p><p>I also think it&#8217;s good that they&#8217;re making these positions explicitly short-term. No one should be joining the government now planning on having job security. And it would not surprise me if there are problems that get solved faster than they would have previously&#8212;for instance, I think if you join, you&#8217;ll quickly get the computers you need with the software you need, which isn&#8217;t nothing.</p><p>Finally, making these programs high-profile, working with industry, targeting folks early enough in their career that they can be paid very competitively <a href="https://www.opm.gov/policy-data-oversight/pay-leave/salaries-wages/2026/general-schedule/">on the GS pay scale</a>&#8212;this is all fine.</p><p>But if your goal with joining these programs is solving actual problems for actual people&#8212;and I hope it is, if you&#8217;re thinking of applying&#8212;there are also significant risks here, and reasons to be skeptical.  The usual structural challenges of government tech still exist, compounded by everything else that&#8217;s happened.</p><p>If you apply, go in with your eyes open. Ask hard questions. Look into the backgrounds of folks running these programs at the agency you&#8217;d be assigned to. Don&#8217;t assume it&#8217;s going to work out. And understand that you&#8217;re not just signing up for a technical challenge; you&#8217;re signing up for a political and organizational one too.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>It is, in fact, true sometimes.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>If you want deeper context on the structural challenges, read Jennifer Pahlka&#8217;s <em><a href="https://www.amazon.com/Recoding-America-Government-Failing-Digital/dp/1250266777">Recoding America</a></em></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>Why do you need buy-in at all? In large bureaucracies, goodwill is incredibly important. That&#8217;s for a few different reasons. One is that other people have the authority you lack and need. Another is that you don&#8217;t know what you don&#8217;t know, and that&#8217;s compounded if you&#8217;re new to the government or even just to that agency. For both reasons, you&#8217;re likely to be reliant on other people to go out of their way to assist you, even if it&#8217;s not exactly their job to do so, and may in fact take them away from their job.</p></div></div>]]></content:encoded></item><item><title><![CDATA[LLMs Already Outperform Data Scientists]]></title><description><![CDATA[Employers Just Haven&#8217;t Realized It]]></description><link>https://presentofcoding.substack.com/p/llms-already-outperform-data-scientists</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/llms-already-outperform-data-scientists</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 08 Dec 2025 13:03:33 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/da07de0a-a6ea-4697-8456-c5d6476dc0ca_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There&#8217;s a William Gibson line: the future is already here, it&#8217;s just not evenly distributed. I spend my days working with AI coding tools and I feel this acutely.</p><p>I held my last real data science job in 2023. Equipped with what exists now<strong>&#8212;</strong>I use Claude Code, but there are other similar tools like Codex and Cursor&#8212;I could have done that 40-hour-a-week job in under ten hours. And that&#8217;s with the meetings and the emails.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>This isn&#8217;t a sustainable equilibrium, and at some point, employers are going to figure it out.</p><h1><strong>What I Did as a Data Scientist</strong></h1><p>Here are some of the kinds of tasks I did in that role as a data scientist:</p><ol><li><p><strong>Talking to people:</strong> briefing clients, managing small projects, getting information from subject matter experts who knew the data.</p></li><li><p><strong>Creating documents:</strong> PowerPoints, short papers, code documentation.</p></li><li><p><strong>Statistics:</strong> deciding what machine learning model to use, or how to solve problems involving distance minimization, or how to reduce the rate of flagging potential errors without causing more real errors to slip through.</p></li><li><p><strong>Coding:</strong> writing Python and SQL to clean data and build reports &#8211; filtering, merging, aggregating. Figuring out how to get my code to post results in Teams or send emails. Making my code run faster on very large data sets. Figuring out how some API worked &#8211; for geocoding, or getting user stats for our dashboards &#8211; and using it. <em>This was by far the biggest part of what I did.</em></p></li></ol><p>By GPT-4, LLMs were already useful for coding and somewhat useful for the kind of statistics I was doing. At this point, they completely smoke me at this kind of work.</p><p>Here&#8217;s what I mean by this: Claude Code can find documentation better and faster than I can. It can synthesize information from multiple sources better and faster. It can write code, run it, read the error message, and fix the problem in the time it would take me to find a relevant Stack Overflow page and read a few responses. It can look at a problem I&#8217;ve never seen before and guess, usually correctly, how it&#8217;s supposed to work based on patterns it&#8217;s seen in a million other codebases.*</p><p>This is no longer just about taking a well-described query and generating the code for it.</p><p>For instance, in 2023, I spent a few weeks trying to figure out the best way to do a specific geographical analysis, and I only got there because an engineer made a great suggestion at a brown bag I was giving. Now, that could have been one conversation with an LLM, and I would have gotten there much faster. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cqtg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cqtg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 424w, https://substackcdn.com/image/fetch/$s_!cqtg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 848w, https://substackcdn.com/image/fetch/$s_!cqtg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 1272w, https://substackcdn.com/image/fetch/$s_!cqtg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cqtg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png" width="516" height="367.8626373626374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1038,&quot;width&quot;:1456,&quot;resizeWidth&quot;:516,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cqtg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 424w, https://substackcdn.com/image/fetch/$s_!cqtg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 848w, https://substackcdn.com/image/fetch/$s_!cqtg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 1272w, https://substackcdn.com/image/fetch/$s_!cqtg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf896f37-9bb6-4c29-b99b-360f213e28f8_1600x1141.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I asked GPT-5.1 the geographical question I was trying to solve back in 2023. The first answer it gave me was the solution I implemented after it was suggested by a developer.</figcaption></figure></div><p>Or, there was the time when I was trying to figure out the best model to use for a machine learning problem&#8211;I had some ideas going in, but ultimately I got the answer from figuring out what outcomes I cared about and then systematically testing out different types of models to see how they performed on those outcomes. Claude Code could have done that with minimal input.</p><p>A lot of what separates pretty good data scientists from bad ones is tolerance for tedium. Willingness to read the documentation. Patience to debug. The discipline to write clean code instead of the spaghetti you might be able to get away with. Maybe you can&#8217;t become a great data scientist on the basis of that&#8212;I don&#8217;t think I was one&#8212; but being willing to just go in there and get the thing done no matter how annoying it was, and even better, get it done in a way that&#8217;s repeatable and clean and that someone else could understand&#8212;a lot of people can&#8217;t or don&#8217;t do that.</p><p>If you can automate that&#8212;and you can&#8212;then the gap between a good data scientist and a bad one gets a lot smaller. This job, as it was done, as I was doing it, becomes not just able to be done faster, but able to be done well by someone who previously wouldn&#8217;t have done a good job. It becomes far less skilled. The curiosity piece still matters&#8212;asking the right questions, really digging into the data, not believing your too-good-to-be-true results until you&#8217;ve sufficiently tried to disprove them&#8212;but even there, the barrier is lower than it was.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bM4p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bM4p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 424w, https://substackcdn.com/image/fetch/$s_!bM4p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 848w, https://substackcdn.com/image/fetch/$s_!bM4p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 1272w, https://substackcdn.com/image/fetch/$s_!bM4p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bM4p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png" width="1170" height="434" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:434,&quot;width&quot;:1170,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bM4p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 424w, https://substackcdn.com/image/fetch/$s_!bM4p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 848w, https://substackcdn.com/image/fetch/$s_!bM4p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 1272w, https://substackcdn.com/image/fetch/$s_!bM4p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1742c158-f51d-4a0a-92df-440f220221f3_1170x434.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is what it looks like to use Claude Code. The thing that took real patience&#8212;tracking down why something isn&#8217;t working&#8212;is now a conversation.</figcaption></figure></div><h1><strong>The Conversation I Keep Having</strong></h1><p>When I talk about this&#8212;for instance, in the context of how important it is to get government employees coding assistant tools, or how useful this has been for me&#8212;I get a couple kinds of pushback.</p><p>The first is &#8220;but it hallucinates&#8221;&#8212;as if that ends the conversation. Yes, LLMs make things up. So I deal with that. When I&#8217;m doing research, I ask for citations, including links and quotes, and I check them. For code, I write a lot more tests than I used to so I can verify the code is doing what I think it&#8217;s doing&#8212;which, like all the coding I do, is now much easier. There&#8217;s a learning curve, but this is not an unsolvable problem. And when people tell me LLMs aren&#8217;t reliable enough, I want to ask: compared to what? Have you seen the code humans write?</p><p>The second isn&#8217;t really an objection&#8212;it&#8217;s more that any conversation about LLMs being useful gets pulled into everything else. Doomerism. Environmental impact. Is AGI coming? Is there a bubble? (Maybe, but there was an internet bubble and we didn&#8217;t all stop using the Internet.) How awful are these tech bros? </p><p>I&#8217;m not dismissing all of those as unimportant, but they&#8217;re different questions from the one I&#8217;m trying to answer here, which is: what can these tools do right now, and what does that mean for work like mine and workers like me?</p><p>Most of the <em>informed</em> skepticism I hear comes from software engineers talking about enterprise software&#8212;large codebases, complex dependencies, production systems. That&#8217;s fair, or at least, I&#8217;m not the right person to argue this point because that&#8217;s not my domain.</p><p>But data science code isn&#8217;t enterprise software. We&#8217;re talking about smaller projects, often just one person. It&#8217;s not software that ships to users&#8212;it&#8217;s pipelines and reports that typically run on your machine or in a cloud environment your employer controls.</p><p>Because of that, the question of huge disruption in my field isn&#8217;t &#8220;are these tools perfect for all coding?&#8221; It&#8217;s &#8220;could someone much less skilled, armed with Claude Code, do better than the person currently in this job?&#8221; And having been a data scientist and worked with data scientists, I think the answer is often yes.</p><p>If you&#8217;re skeptical of this, I&#8217;d say: talk to your developer friends who are seriously engaging with these tools. The ones who are using Claude Code or Cursor all day, every day. Ask them what their work looks like now versus two years ago. Ask them if they&#8217;d go back. And try the latest models and tools yourself for research and data analysis. Treat it like any new technology, where you assume you&#8217;ll need to put some time into learning how to use it.</p><h1><strong>Where I Am Now</strong></h1><p>I was recently assisting a colleague who was newer to LLMs. They were trying to get a program to work and asking ChatGPT to help. They told it the software had errored, but they didn&#8217;t think to paste in the error message. It reminded me: I&#8217;ve been talking to these things constantly for years. Most people haven&#8217;t. The steps that have become automatic for me&#8212;what to ask, what context to give, how to check the output&#8212;none of that is obvious yet. And neither is it obvious what they can do.</p><p>That&#8217;s the gap. Not capability&#8212;we&#8217;re past that, at least in data science. It&#8217;s that most people haven&#8217;t learned how to use these tools, and most organizations haven&#8217;t figured out how to integrate them. The lack of labor market disruption so far is a matter of implementation, not capability. That&#8217;s what&#8217;s buying time.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Make Things, Tell People]]></title><description><![CDATA[On side projects and finding work]]></description><link>https://presentofcoding.substack.com/p/make-things-tell-people</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/make-things-tell-people</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 17 Nov 2025 13:11:48 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/58cc742e-75bb-4139-bda8-f271fae34fbf_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I got my first job post-graduate school via a board game weekend<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>. Not a tech conference, not a networking event. I mentioned the research I was doing to another graduate student who matched me with someone looking to hire for very similar work.</p><p>Years later, with a lot more experience, I&#8217;m still currently not finding work through traditional application processes. When I left my job with the federal government in May, I decided it was going to be a better use of my time to build things than to send out resumes. I sent a few applications&#8212;Anthropic, still waiting to hear from you!&#8212;but by and large, it wasn&#8217;t something I even tried.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The short story: it worked out. I wound up with contract work I wanted, and it came entirely from a mix of side projects, networking via side projects, and previous coworkers. The mechanism is different now than it was in grad school&#8212;I have a network, and I can&#8217;t overstate how much that helped&#8212;but the pattern is the same as for that earlier job: make things, tell people.</p><p>And for that first job, I got lucky&#8212;I happened to be doing research someone was interested in. But after that, side projects were consistently what made the difference. Side projects let you make more of your own luck. You get to choose what you work on and what story you&#8217;re able to tell, instead of hoping your coursework or current job happens to match what someone wants and what you want to be doing. Side projects help in two ways&#8212;they can lead to opportunities through networking, but they also make your traditional applications much stronger when you do just apply.</p><p>I write this because college students and people making career changes get in touch with me asking for advice, and I find myself being weirdly reluctant to tell anyone they should spend their free time on side projects, even though it&#8217;s what I do. And in a strong hiring market, traditional applications with coursework and internships work fine. But this is not that market. Managers are looking at hundreds or thousands of interchangeable resumes with the same coursework and the same &#8216;proficient in Python and SQL.&#8217; You can&#8217;t retroactively change the school you went to or what your grades were, but you can build interesting, new things.</p><h1><strong>Why This Works</strong></h1><p>Side projects have a few built-in advantages that can be very hard to get otherwise, depending on your background:</p><ol><li><p><strong>Problem definition and solving.</strong> They let you figure out what problem is worth solving and how to solve it&#8212;as opposed to coursework, where you&#8217;re generally assigned problems that someone has figured out are solvable already. In this sense, this mimics work a lot more closely.</p></li><li><p><strong>Clear individual contribution.</strong> They let you build something by yourself, so people can tell it was you, and in a way that you can make fully public&#8212;as opposed to work projects you&#8217;re not allowed to share and where it&#8217;s hard to tell what your role was.</p></li><li><p><strong>Demonstrating genuine interest.</strong> Side projects are strong signal that you care about that topic.</p></li><li><p><strong>Showing agency.</strong> You trusted yourself that something was worth doing and that you could do it. And then you did it.</p></li></ol><p>These reasons also point to why some side projects work better than others. If you&#8217;re analyzing a data set that&#8217;s been done to death already, it&#8217;s harder to tell what you specifically contributed vs. took from someone else in terms of both the approach and the execution. It also doesn&#8217;t give you the chance to pick something that&#8217;s unique to you and your interests. This doesn&#8217;t mean you shouldn&#8217;t do that kind of side project&#8212;maybe you&#8217;re just doing this to learn a particular skill, in which case it doesn&#8217;t matter what anyone else thinks of it. But if you&#8217;re avoiding doing your own thing because you think every project has been done already and so you can&#8217;t possibly do anything new, this is false, and you absolutely can.</p><p>And all of these advantages matter whether you&#8217;re networking your way into opportunities or strengthening a traditional application. </p><h1><strong>How to Do It</strong></h1><h2><strong>Finding ideas</strong></h2><p>I spend a lot of time in places where people are talking about problems they have or topics they&#8217;re curious about. <a href="https://www.meetup.com/data-science-dc/">Data Science DC</a> meetups, Signal chats where people talk about government tech, LinkedIn. When something really catches my attention, I start trying to figure out if there&#8217;s something small I can build to answer a question or solve a problem.</p><p>If you&#8217;re not in these spaces yet, start going to local tech meetups, free conferences, hackathons&#8212;whatever exists near you<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. Listen to the talks. Pay attention to what problems people mention and what tools they use. For instance, you&#8217;ll see that GitHub isn&#8217;t optional even if your classes didn&#8217;t teach you how to use it properly. R is still used, but more frequently on teams where Python is as well. Polars and DuckDB are increasingly common. A lot of work involves LLMs. <strong>The tools people are using in their work and giving talks about are the tools you should be using in your side projects</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a><strong>.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Z8s_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Z8s_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 424w, https://substackcdn.com/image/fetch/$s_!Z8s_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 848w, https://substackcdn.com/image/fetch/$s_!Z8s_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 1272w, https://substackcdn.com/image/fetch/$s_!Z8s_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Z8s_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png" width="712" height="313" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d596a146-855b-476d-a302-52511857a05d_712x313.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:313,&quot;width&quot;:712,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Z8s_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 424w, https://substackcdn.com/image/fetch/$s_!Z8s_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 848w, https://substackcdn.com/image/fetch/$s_!Z8s_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 1272w, https://substackcdn.com/image/fetch/$s_!Z8s_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd596a146-855b-476d-a302-52511857a05d_712x313.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">If you&#8217;re early-career and technical, even if you&#8217;re only applying for job the normal way, you should probably still have a GitHub profile and link to it on your resume</figcaption></figure></div><p>A recent project: I&#8217;d been hanging out in spaces where people talk about government open source, and I&#8217;d also recently worked with the GitHub API to pull commit data. I added those two things up and spent a couple evenings making a site that <a href="https://federal-github-activity.netlify.app/">pulls data from government GitHub accounts to see what agencies are making code public</a>. It wasn&#8217;t a big idea at all, it was just noticing two things I already thought about and connecting them.</p><p>That&#8217;s the pattern. Someone posts on LinkedIn. Or mentions something at a meetup. You read an article and think &#8220;wait, is that actually true?&#8221; And instead of just wondering about it, you go build something.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TNp1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TNp1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 424w, https://substackcdn.com/image/fetch/$s_!TNp1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 848w, https://substackcdn.com/image/fetch/$s_!TNp1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 1272w, https://substackcdn.com/image/fetch/$s_!TNp1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TNp1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png" width="1456" height="655" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:655,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:249478,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/179102693?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!TNp1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 424w, https://substackcdn.com/image/fetch/$s_!TNp1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 848w, https://substackcdn.com/image/fetch/$s_!TNp1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 1272w, https://substackcdn.com/image/fetch/$s_!TNp1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6d80b72-47d0-4b92-8e08-9febf45d222a_2214x996.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The fun new part of this for me was previewing how it would look on my cell phone and doing mobile-specific formatting</figcaption></figure></div><h2>Telling people about it</h2><p>Making the thing is only half of it. The other half is telling people.</p><p>I go back to the same spaces where I found ideas and share what I built. But also, I&#8217;ve messaged strangers to offer them data, and sometimes they say yes. I write blog posts so that later, when I&#8217;m talking to someone about that topic, I have something to send them.</p><p>When you show up in these spaces&#8212;especially if you&#8217;re early in your career&#8212;lead with what you&#8217;re working on or what you&#8217;re curious about, not with &#8220;I&#8217;m looking for a job&#8221;. &#8220;I was messing around with MCP servers and here&#8217;s what I built&#8221; is memorable and gives a sense of your interests and capabilities. &#8220;I&#8217;m looking for a data analyst role&#8221; does not.</p><p>And public events are just the first step. A lot of opportunities happen in private groups and conversations, but you&#8217;ll never meet the people who might invite you unless you engage with the public spaces first.</p><p>Telling people about it also includes putting it on your resume, along with links.</p><h1><strong>What You Get Out of This</strong></h1><p>I&#8217;m not saying this is how job hunting should work. And if you can find the job you want without doing any of this&#8212;the side projects or the networking&#8212;that&#8217;s great. I&#8217;m writing this because I don&#8217;t reliably know how to do that, so I do this instead, and I&#8217;m happy with how it&#8217;s worked out for me over the years. </p><p>Part of why I&#8217;m happy with it is that building things I find interesting is a lot less grim than sending out applications. It doesn&#8217;t feel like wasted time. And each project builds your skills&#8212;both the technical ones, but also the pattern of seeing a problem and making something that responds to it.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>It was affiliated with a local university, and that&#8217;s absolutely doing some of the work in this story.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>This is easier if you&#8217;re in a major city where these events exist and where there&#8217;s density of people in your field. If you&#8217;re not, you might need to be more deliberate&#8212;finding online communities and focusing more heavily on building a visible online presence through blog posts and LinkedIn.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>I wrote more about GitHub and &#8216;good development practices&#8217; <a href="https://presentofcoding.substack.com/p/github-how-to-tell-your-professional">here</a>.</p></div></div>]]></content:encoded></item><item><title><![CDATA[My Cheap Side-Project Tech Stack]]></title><description><![CDATA[Data pipelines on a budget]]></description><link>https://presentofcoding.substack.com/p/my-cheap-side-project-tech-stack</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/my-cheap-side-project-tech-stack</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Thu, 30 Oct 2025 12:02:35 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/1dd84010-35f9-443e-abe8-6741b02d96fd_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the summer, I built out data pipelines that populate <a href="https://usajobs-tracker.netlify.app/">websites</a>, mostly with federal jobs listing data from <a href="https://www.usajobs.gov/">USAJobs</a>.</p><p>This was new for me. I&#8217;m coming from data science, and I&#8217;d built reports which updated regularly and sent emails, but most of them ran inside Databricks&#8212;a system someone else maintained, pulling from data tables someone else updated&#8212;and they never had their own websites. This was the first time I was building something like this all the way through by myself. At the same time, these were also side projects, and I didn&#8217;t want to spend a lot of money on them.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Initially, I just ran the update scripts manually when I remembered. Then I got tired of that and wanted it all online. Then I realized I needed tests because things were breaking and I wouldn&#8217;t figure it out until I checked the website&#8212;or, worse, someone else told me. My setup came together piece by piece as I needed it.</p><p>Here&#8217;s where I landed.</p><h2><strong>GitHub Large File Storage (LFS)</strong></h2><p><strong>The problem:</strong> I had too much data to commit to GitHub the normal way: GitHub won&#8217;t let you commit files over 100MB, and my Parquet files with years of job listings were bigger than that. But I wasn&#8217;t ready to set up a database&#8212;that felt like overkill.</p><p><strong>How it works:</strong> <a href="https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-git-large-file-storage">GitHub LFS</a> stores large files separately and keeps pointers in Git. You tell Git which file types to track with LFS, and it handles the rest.</p><p><strong>My implementation:</strong> All my big data files go into LFS. When my GitHub Actions workflow runs&#8212;more on that later&#8212;it pulls those files to process them. This way, the data stays versioned and can live on GitHub.</p><p><strong>When to use it:</strong> When you&#8217;re accumulating data over time and need version control but aren&#8217;t ready for a database. It costs $5/month for 50GB of storage and bandwidth; some months I pay more, when people are cloning my repos.</p><h2><strong>GitHub Actions</strong></h2><p><strong>The problem:</strong> I needed my pipeline to run automatically. Running scripts manually on my laptop when I remembered wasn&#8217;t sustainable.</p><p><strong>How it works:</strong> GitHub Actions runs code on GitHub&#8217;s servers based on schedules you set. For instance, you write a workflow file that says &#8220;run this Python script every day at 4 AM.&#8221; Actions spins up a virtual machine, checks out your code, installs dependencies, runs your scripts, and can push results back to your repo or even create and resolve pull requests to other branches.</p><p><strong>My implementation:</strong> I have several actions that run daily and a couple that are more infrequent. They check out the repo with LFS files, install dependencies, run the data collection scripts, then run tests.</p><p>What typically breaks when I&#8217;m first setting these up are dependencies and permissions.</p><p>For dependencies, you spell out everything. Not just Python packages, but if you&#8217;re web scraping with Playwright, you need Playwright AND the browser AND system dependencies. If you&#8217;re calling APIs, you need API keys in GitHub Secrets. Everything your local environment has, Actions needs explicitly declared.</p><p>For permissions, the workflow also needs explicit grants to write to your repo or create pull requests. Without these, your workflow fails.</p><p><strong>Writing tests:</strong> I test what I&#8217;m worried might break AND what would be bad if it broke. For instance, my tests check that data files exist, aren&#8217;t empty, and have required columns. I don&#8217;t have tests for things like my JavaScript filters, because I&#8217;ve decided that what I&#8217;m most concerned about is data integrity, and I wasn&#8217;t quite ready to also add website testing as well.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UbRQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UbRQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 424w, https://substackcdn.com/image/fetch/$s_!UbRQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 848w, https://substackcdn.com/image/fetch/$s_!UbRQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 1272w, https://substackcdn.com/image/fetch/$s_!UbRQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UbRQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png" width="318" height="480.8970588235294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1234,&quot;width&quot;:816,&quot;resizeWidth&quot;:318,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!UbRQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 424w, https://substackcdn.com/image/fetch/$s_!UbRQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 848w, https://substackcdn.com/image/fetch/$s_!UbRQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 1272w, https://substackcdn.com/image/fetch/$s_!UbRQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8053d6cc-5fc2-485d-8dc6-e49d3147f6c7_816x1234.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is my workflow</figcaption></figure></div><p>When something breaks in an unexpected way, add a test for it. When I accidentally deleted some of my data, I added a test that checks for every job listing that was in the files last time this action ran. If a test fails, the workflow stops.</p><p><strong>When to use it:</strong> When you need scheduled, automated work without running servers. Public repos get unlimited Action minutes. Private repos get 2,000 free minutes per month. Each job has a 6-hour timeout.</p><h2><strong>Multiple Branches</strong></h2><p><strong>The problem:</strong> I needed stage/prod separation without servers. But how do you test changes when everything happens in the same repository and you have no budget?</p><p><strong>How it works:</strong> Use branches as environments. Your pipeline pushes updates to a staging branch. Tests run automatically. Only if tests pass does anything merge to main, then push to a production branch that your website deploys from. (Your exact branch structure may differ.)</p><p><strong>My implementation:</strong> Each day, my workflow creates a fresh staging branch from main, runs the pipeline, and commits results. Tests run. If they pass, the workflow auto-creates a pull request to main and auto-merges it. Finally, it pushes to my production branch, which my website deploys.</p><p>The flow: staging &#8594; tests &#8594; auto-merge to main &#8594; push to production &#8594; website deploys.</p><p><strong>When to use it:</strong> When you need to test before you deploy, but you&#8217;re not running servers. The branch-based approach gives you stage/prod separation without infrastructure costs.</p><h2><strong>Netlify</strong></h2><p><strong>The problem:</strong> I needed to host websites that updated automatically, stayed fast, and didn&#8217;t cost money.</p><p><strong>How it works:</strong> <a href="https://www.netlify.com/">Netlify</a> hosts static sites&#8212;just HTML, CSS, and JavaScript files, no backend fetching from a database or running Python. You can set it up so that Netlify watches a specific GitHub branch, and whenever you push to that branch, it automatically deploys your site.</p><p><strong>My implementation:</strong> Netlify monitors only my production branch. When GitHub Actions pushes there (after tests pass), Netlify builds the site and then deploys. I stay within the free tier.</p><p>Static sites are simpler, which means less to break. But there&#8217;s a constraint: you can&#8217;t load huge amounts of data all at once. Load a 50MB JSON file on page load and it will crawl&#8212;or fail outright.</p><p><strong>The data split trick:</strong> When I have a lot of raw data, I split it into multiple files&#8212;one for each filter value. For USAJobs, that means I create separate files with the raw jobs data for each federal department. To see raw data, users must filter by department first, which triggers loading just that department&#8217;s file. Each file is small, so it loads quickly.</p><p><strong>When to use it:</strong> When you want simple deployment and don&#8217;t need a backend. Netlify&#8217;s free tier: 100GB bandwidth per month and 300 build minutes.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e-Uz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e-Uz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 424w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 848w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1272w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png" width="558" height="205.22188449848025" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:484,&quot;width&quot;:1316,&quot;resizeWidth&quot;:558,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!e-Uz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 424w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 848w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1272w, https://substackcdn.com/image/fetch/$s_!e-Uz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5d012a5-2ed6-4c8d-bd54-bb4c712b9b0a_1316x484.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Most of my sites don&#8217;t take very long to build, so it only got to 252 through a lot of fixing/deploying</figcaption></figure></div><h2><strong>D3 and DataTables</strong></h2><p><strong>The problem:</strong> With my sites, I needed interactivity&#8212;users filtering data, searching tables, clicking on visualizations. Python can&#8217;t run in the browser. JavaScript is what runs client-side, which means it&#8217;s what you need for static sites to do anything interactive.</p><p>The secondary benefit: I also wanted very specific visualizations. For static graphs, Python has great options. But for interactive web visualizations&#8212;bubble maps, filterable charts&#8212;I wasn&#8217;t happy with what I was able to make.</p><p><strong>How it works:</strong> JavaScript runs in the browser. <a href="https://d3js.org/">D3</a> is a JavaScript library for data-driven visualizations. <a href="https://datatables.net/">DataTables</a> is a library that adds sorting, filtering, and search to HTML tables. The ecosystem is huge: if you need a specific chart or interaction, someone has probably built a component you can use.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mA85!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mA85!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 424w, https://substackcdn.com/image/fetch/$s_!mA85!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 848w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1272w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mA85!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png" width="1456" height="528" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:528,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!mA85!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 424w, https://substackcdn.com/image/fetch/$s_!mA85!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 848w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1272w, https://substackcdn.com/image/fetch/$s_!mA85!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F677f0fd5-9eb9-4712-b39b-825d0e4953c3_2048x742.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is a bubble chart in D3</figcaption></figure></div><p><strong>My implementation:</strong> I use DataTables for tables&#8212;it gives me instant search and filter functionality without building it myself. For graphics, I use D3. I still don&#8217;t know JavaScript&#8212;I use Claude Code to write it<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>. But I knew enough from Python to recognize patterns like &#8220;I should abstract this out because I keep using it&#8221; or &#8220;use DataTables for search instead of building your own.&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pZ_B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pZ_B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 424w, https://substackcdn.com/image/fetch/$s_!pZ_B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 848w, https://substackcdn.com/image/fetch/$s_!pZ_B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 1272w, https://substackcdn.com/image/fetch/$s_!pZ_B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pZ_B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png" width="1456" height="435" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:435,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!pZ_B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 424w, https://substackcdn.com/image/fetch/$s_!pZ_B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 848w, https://substackcdn.com/image/fetch/$s_!pZ_B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 1272w, https://substackcdn.com/image/fetch/$s_!pZ_B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb966d298-9044-42be-a6b6-c7ba4ed04988_2048x612.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This uses <a href="http://datatables.js">DataTables.js</a></figcaption></figure></div><p><strong>When to use it:</strong> When you&#8217;re building sites and need interactivity and specific data visualizations. Use existing components instead of building everything yourself.</p><h2><strong>What This Costs</strong></h2><p>Almost everything here is free. GitHub Actions is free for public repos. Netlify&#8217;s free tier covers all the hosting I need. The only real cost is GitHub LFS.</p><p>The more significant cost was my time. Getting permissions right, understanding when tests needed to run, realizing I needed branch-based environments&#8212;that took a lot of trial and error. But as I learned, the incremental time it took for each new site or action got lower.</p><p>Now it runs without me. The pipeline updates daily, tests catch the problems that I care about the most, bad data never reaches production, and the website stays current.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Claude Code, if you count it as part of my stack, is by far the most expensive thing in it&#8212;but also the only reason I have working JavaScript.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Five LLM Tricks for Data Pipelines]]></title><description><![CDATA[The LLM unstructured text pipeline that I write about is everywhere.]]></description><link>https://presentofcoding.substack.com/p/five-llm-tricks-for-data-pipelines</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/five-llm-tricks-for-data-pipelines</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 27 Oct 2025 12:03:09 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e09eded9-ec88-4241-8f0a-4af1273dbfcb_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <a href="https://presentofcoding.substack.com/p/adding-structure-to-your-text-data">LLM unstructured text pipeline</a> that I write about is everywhere. In it, you have a prompt, you have text data (PDFs, user input, spreadsheet rows), you iterate through each one and get structured output like summaries, classifications, or extracted information. </p><p>Last week, one explained to me their data pipeline&#8212;which was a very standard version of this&#8212;AND another person told me about a tool their organization deployed that lets users do this without any coding.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Point made! I think I can stop writing about this pattern. So this is, instead, about a handful of other text-processing tricks I use LLMs for as part of data pipelines. </p><p>Most of these you could fold into your unstructured text pipeline; a couple work alongside tools like regular expressions or semantic clustering. They&#8217;re all variations on the same principle: if it&#8217;s a repetitive text processing task that&#8217;s easy-to-explain and doesn&#8217;t require a ton of judgement, you can write that into your data pipeline and have an LLM do it for you.</p><h2><strong>1. Column Discovery</strong></h2><p><strong>The problem</strong>: Your pipeline processes data that&#8217;s fairly standardized, but column names and formats may vary between datasets.</p><p><strong>The trick</strong>: Describe what you&#8217;re looking for to an LLM, give it information about the dataset (column names, the first few rows, information on how many values are missing and what the most common values are&#8212;basically, whatever you&#8217;d give a human analyst), and have it populate a JSON file mapping your standard field names to what this specific dataset calls them. Use that JSON in the rest of your pipeline.</p><p><strong>Real example</strong>: In my comment analyzer for regulations.gov bulk data, column names are usually the same, but not always. Because of this, I have an automated step that figures out the mapping: in this case, I just give it the first five rows, because that seems to work. The alternative would be maintaining an exhaustive list of every variation and either hard-coding them all or using pattern matching to anticipate future changes, or else doing this manually each time.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GlE0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GlE0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 424w, https://substackcdn.com/image/fetch/$s_!GlE0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 848w, https://substackcdn.com/image/fetch/$s_!GlE0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 1272w, https://substackcdn.com/image/fetch/$s_!GlE0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GlE0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png" width="1456" height="651" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:651,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:170538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/177186763?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GlE0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 424w, https://substackcdn.com/image/fetch/$s_!GlE0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 848w, https://substackcdn.com/image/fetch/$s_!GlE0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 1272w, https://substackcdn.com/image/fetch/$s_!GlE0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b3eeb57-214b-4c4f-97b3-6692d65c5d58_1788x800.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is part of <a href="https://github.com/abigailhaddad/generic-comment-analyzer/blob/main/detect_columns.py">my code for column identification</a>. </figcaption></figure></div><p><strong>When to use it</strong>: When you have semi-standardized data with naming variations. You can run this with user validation (showing them the mapping and letting them confirm or correct it) or without&#8212;but if it&#8217;s without, I think you should build in some automated validation that you found the right columns (like checking that the data types make sense), which will still be easier than trying to do column identification without the LLM.</p><h2><strong>2. Theme Discovery and Prompt Writing</strong></h2><p><strong>The problem</strong>: You need to classify text, but the relevant classification buckets you&#8217;re looking for, like what themes are present in the data, are different for each dataset.</p><p><strong>The trick</strong>: Give the LLM a prompt describing what you&#8217;re looking for, plus a random sample of your text. It synthesizes the themes faster than you could, determining what buckets to classify the text into and writing the exact prompts. Your pipeline then takes this output and uses it to populate both the prompt text and the <a href="https://presentofcoding.substack.com/p/the-one-pattern-i-use-in-every-llm">Pydantic class structure</a>, so the LLM can only choose from the themes it identified, not make up new ones.</p><p><strong>Real example</strong>: For my public comment analysis, the arguments people make of course vary by regulation. I let the LLM <a href="https://github.com/abigailhaddad/generic-comment-analyzer/blob/main/discover_stances.py">read a sample, identify the main arguments according to a very specific set of rules, and write the prompts and values that will be used to classify all the comments</a>.</p><p><strong>When to use it</strong>: When classification categories aren&#8217;t predetermined&#8212;this could be themes in comments, types of errors in logs, categories of customer feedback, or any other situation where the buckets themselves need to be discovered from the data. Depending on the use case, you might let users validate the LLM&#8217;s choices about buckets or prompts if they want something different.</p><h2><strong>3. Hybrid LLM/Regular Expressions</strong></h2><p><strong>The problem</strong>: You have too much data to send each document to an LLM, maybe because of cost or processing time, but you still want to extract things that would be tedious to hard-code manually.</p><p><strong>The trick</strong>: Sample from your documents and use an LLM to extract what you&#8217;re looking for. Deduplicate the results, optionally set a threshold (like &#8220;appears in at least 2% of documents&#8221;), then use string matching or regular expressions to find those items in your full dataset.</p><p><strong>Real example</strong>: Processing resumes at scale&#8212;extracting programming languages, frameworks, tools. The LLM tells you what&#8217;s in the data without you spending hours building and maintaining lists. You can also model the likelihood that additional sampling would find new items, and monitor over time to catch new terms appearing in resumes.</p><p><strong>When to use it</strong>: This works for terms that aren&#8217;t one-offs in the documents you&#8217;re analyzing. For instance, programming languages like &#8220;Python&#8221; appear the same way across many resumes, so once you&#8217;ve identified them with the LLM, you can use pattern matching to find them everywhere else. But it won&#8217;t work as well for things with too many possible values&#8212;like college names or job titles. So for certain types of entities (names, places, organizations), you&#8217;d need a different approach&#8212;like a smaller model specifically designed for entity recognition, like GLiNER, possibly fine-tuned with labeled examples you got from the LLM.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ejOs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ejOs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 424w, https://substackcdn.com/image/fetch/$s_!ejOs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 848w, https://substackcdn.com/image/fetch/$s_!ejOs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 1272w, https://substackcdn.com/image/fetch/$s_!ejOs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ejOs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png" width="1456" height="384" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:384,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:137959,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/177186763?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ejOs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 424w, https://substackcdn.com/image/fetch/$s_!ejOs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 848w, https://substackcdn.com/image/fetch/$s_!ejOs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 1272w, https://substackcdn.com/image/fetch/$s_!ejOs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f73745c-53ee-4cc8-acf7-613db581fc66_1736x458.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">What makes <a href="https://github.com/urchade/GLiNER">GliNER</a> cool is that it&#8217;s not limited to &#8220;predefined entities&#8221;: you can put in a brand-new entity type that is not previously defined</figcaption></figure></div><h2><strong>4. Matching with LLMs</strong></h2><p><strong>The problem</strong>: You need to match items between two datasets, but exact matching won&#8217;t work and lexical matching, or comparing how similar strings are based on the actual characters or words, isn&#8217;t smart enough.</p><p><strong>The trick</strong>: Do a first pass with lexical matching and heuristics like date proximity or other filtering rules to get close matches. For anything below your confidence threshold, pass the top candidates to an LLM to make the final call.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tIWs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tIWs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 424w, https://substackcdn.com/image/fetch/$s_!tIWs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 848w, https://substackcdn.com/image/fetch/$s_!tIWs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 1272w, https://substackcdn.com/image/fetch/$s_!tIWs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tIWs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png" width="594" height="275.7096774193548" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:518,&quot;width&quot;:1116,&quot;resizeWidth&quot;:594,&quot;bytes&quot;:78664,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/177186763?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tIWs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 424w, https://substackcdn.com/image/fetch/$s_!tIWs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 848w, https://substackcdn.com/image/fetch/$s_!tIWs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 1272w, https://substackcdn.com/image/fetch/$s_!tIWs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434c468f-e9d4-4d04-ae04-a82a338dc3b7_1116x518.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is the workflow</figcaption></figure></div><p><strong>Real example</strong>: In my congressional hearing matcher, I&#8217;m matching YouTube videos to their Congress.gov records. For instance, &#8220;Health Subcommittee Markup of 23 Bills&#8221; versus &#8220;23 Pieces of Legislation&#8221; use completely different words but refer to the same event. <a href="https://github.com/abigailhaddad/hearings/blob/main/scripts/match_with_llm.py">Lexical matching and date filtering narrow it down, then the LLM adjudicates unclear cases via a more nuanced matching process</a>.</p><p><strong>When to use it</strong>: When you&#8217;re matching things where the relationship isn&#8217;t captured by business rules. This is a variation of the standard text pipeline, but I&#8217;m including it because the possible outputs do vary for each &#8216;document&#8217;: your lexical/business rule process limits the options that the LLM can return.</p><h2><strong>5. Naming Clusters with LLMs</strong></h2><p><strong>The problem</strong>: You&#8217;ve done semantic clustering on your text data, but the clusters are just numbers or unlabeled groups.</p><p><strong>The trick</strong>: After clustering, pass representative examples and the list of the most common or most-distinguishing words or phrases from each cluster to an LLM and have it generate human-readable labels that capture what the cluster is about.</p><p><strong>Real example</strong>: In my <a href="https://presentofcoding.substack.com/p/government-document-analysis">Schedule F comment analysis</a>, I clustered semantically similar comments together. Then I <a href="https://github.com/abigailhaddad/schedule_f/blob/main/backend/analysis/cluster_descriptions.py">pass the LLM samples and common words from each cluster and it describes them</a>. This is faster than reading through clusters myself, and especially useful when your clusters may change over time with new data.</p><p><strong>When to use it</strong>: After any clustering or grouping where you need human-interpretable labels. The LLM is doing synthesis work you&#8217;d otherwise do manually.</p><h2><strong>The Pattern</strong></h2><p>These tricks all follow the same logic: they&#8217;re tasks you can give clear instructions for, and they&#8217;re not inherently complicated&#8212;but they&#8217;d still take you time to do manually. An LLM can do them quickly and frequently well enough, and you can add in a human validation step if you want.</p><p>I&#8217;m especially interested in LLM/non-LLM hybrid patterns like #3. The hybrid approach splits the work: the LLM samples your documents and extracts terms, then you use those terms with regular expressions to search your full dataset. You get the LLM&#8217;s ability to identify what&#8217;s actually in your data without manually building lists, combined with speed and transparency for the bulk processing.</p><p>This structure also builds in error tolerance. If your LLM sample occasionally misses &#8220;Ruby,&#8221; you&#8217;ll probably see it in the next sample batch. You can also check completeness by comparing your found terms with your samples&#8212;and because you can model the likelihood of finding new terms by continuing to sample more, you can also quantify your sampling coverage. It&#8217;s also an example of using the LLM to label data for use with smaller models&#8212;similar to using LLMs to extract entities and use those labels to test or fine-tune your entity model, except in this case your &#8220;model&#8221; is just the presence or absence of each word.</p><p>Working with different kinds of text data pipelines makes these patterns easier to see. The more you do it, the faster you recognize when you need a new one.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The Pattern I Use in Every LLM Project]]></title><description><![CDATA[Pydantic and LiteLLM for structured output]]></description><link>https://presentofcoding.substack.com/p/the-one-pattern-i-use-in-every-llm</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/the-one-pattern-i-use-in-every-llm</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 29 Sep 2025 12:03:17 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f5ec16e2-e6fc-4c8e-b176-f6cc665b84fc_1024x1536.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every time I process text with LLMs&#8212;whether it&#8217;s analyzing public comments, matching YouTube videos to congressional hearings, or summarizing research papers&#8212;I use the same pattern to get my output from the model.</p><p>In the early days of ChatGPT, I had projects where half my prompt was begging the model to <strong>ONLY SAY YES OR NO</strong> or <strong>GIVE THIS TO ME AS A LIST</strong>. Sometimes it worked. Often it didn&#8217;t, and I was stuck cleaning up the output. The model would give me a paragraph about why something might be yes or no, when all I needed was the answer.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Then the <a href="https://askmarvin.ai/welcome">Marvin</a> library came out and fixed this for OpenAI models: instead of begging or lecturing, you could just describe the behavior of the LLM and your output would come back formatted correctly. I heard <a href="https://www.youtube.com/watch?v=5fhmSHYasME">Adam Azzam</a> talk about it at a meetup, and that weekend I rebuilt my project. Suddenly, I could define exactly what structure I wanted back, and the model would comply.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xuaM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xuaM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 424w, https://substackcdn.com/image/fetch/$s_!xuaM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 848w, https://substackcdn.com/image/fetch/$s_!xuaM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 1272w, https://substackcdn.com/image/fetch/$s_!xuaM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xuaM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png" width="1456" height="494" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:494,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:87904,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/174718954?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xuaM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 424w, https://substackcdn.com/image/fetch/$s_!xuaM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 848w, https://substackcdn.com/image/fetch/$s_!xuaM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 1272w, https://substackcdn.com/image/fetch/$s_!xuaM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F093a90ed-5c6b-4e7f-90a4-f42b81067ab0_1596x542.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">In the initial Marvin documentation, sorting into a Hogwarts house used to be one of the examples. I couldn&#8217;t find it anymore&#8212;I wrote this one myself&#8212;but the text was this minimal, which was a big deal at the time. </figcaption></figure></div><p>Now this general pattern&#8212;where you describe the behavior you want&#8212;is built into many LLMs natively. Here&#8217;s what it looks like, using LiteLLM, a library that provides a consistent interface across different LLM providers. In the following example, we use an LLM to characterize text as support, oppose, or neutral, and we get a list of the main arguments it's making. </p><pre><code>from pydantic import BaseModel, Field
from enum import Enum
import litellm
import json

litellm.api_key=your_api_key # Replace this with your actual key!

class Stance(str, Enum):
    SUPPORT = &#8220;support&#8221;
    OPPOSE = &#8220;oppose&#8221;
    NEUTRAL = &#8220;neutral&#8221;

class CommentAnalysis(BaseModel):
    stance: Stance = Field(
        description=&#8221;&#8217;support&#8217; if favoring proposal, &#8216;oppose&#8217; if against, &#8216;neutral&#8217; if no clear position&#8221;
    )
    key_points: list[str] = Field(
        description=&#8221;Main arguments from the comment&#8221;
    )

comment_text = &#8220;&#8221;&#8220;I can&#8217;t believe anyone is considering this.
It will hurt small businesses and increase costs for consumers.
Read an economics textbook, losers.&#8221;&#8220;&#8221;

response = litellm.completion(
    model=&#8221;gpt-4o-mini&#8221;,
    messages=[
        {&#8221;role&#8221;: &#8220;system&#8221;, &#8220;content&#8221;: &#8220;Analyze public comments on regulations. Determine stance (support/oppose/neutral) and extract key points.&#8221;},
        {&#8221;role&#8221;: &#8220;user&#8221;, &#8220;content&#8221;: f&#8221;Analyze this comment: {comment_text}&#8221;}
    ],
    response_format=CommentAnalysis,
    temperature=0.0
)</code></pre><p>That&#8217;s the core of it. The model returns the structure you defined, with stance limited to your three options, and with a list of arguments. </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2HSN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2HSN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 424w, https://substackcdn.com/image/fetch/$s_!2HSN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 848w, https://substackcdn.com/image/fetch/$s_!2HSN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 1272w, https://substackcdn.com/image/fetch/$s_!2HSN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2HSN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png" width="1294" height="254" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:254,&quot;width&quot;:1294,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:43441,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/174718954?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2HSN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 424w, https://substackcdn.com/image/fetch/$s_!2HSN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 848w, https://substackcdn.com/image/fetch/$s_!2HSN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 1272w, https://substackcdn.com/image/fetch/$s_!2HSN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb707335-6925-4774-bbd7-54e6eeff1d0e_1294x254.png 1456w" sizes="100vw"></picture><div></div></div></a><figcaption class="image-caption">This is the result I got from the earlier code</figcaption></figure></div><p><strong>Important caveat: This is just about getting your output structured correctly&#8212;the content might still be wrong!</strong> </p><h2><strong>Why This Works So Well</strong></h2><p>Three components make this pattern work:</p><ul><li><p><strong>Pydantic</strong> declares fields, like Stance, and types, like string or list</p></li><li><p><strong>Enums</strong> constrain choices (yes/no, support/oppose/neutral, high/medium/low)</p></li><li><p><strong>LiteLLM</strong> provides a portable interface so you aren&#8217;t rewriting provider-or model-specific glue to call the LLM. </p></li></ul><h2><strong>A Real Example: Matching Congressional Hearings to YouTube</strong></h2><p>For the <a href="https://www.house.gov/Hackathon">Congressional hackathon</a> recently, I needed to match YouTube videos of hearings (the first data set) with their official Congress.gov records (the second data set). The problem is that, while we have the titles and dates in both, they frequently don&#8217;t match exactly across data sets.</p><p>For instance, &#8220;Health Subcommittee Markup of 23 Bills&#8221; and &#8220;23 Pieces of Legislation&#8221; use almost entirely different words, but refer to the same event.</p><p>My approach:</p><ol><li><p><strong>First pass: Heuristics.</strong> Date matching and lexical title similarity (comparing the actual words, not the meaning)</p></li><li><p><strong>Second pass: LLM adjudication.</strong> For uncertain cases, hand the top matches to an LLM and ask it to decide.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PWNf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PWNf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 424w, https://substackcdn.com/image/fetch/$s_!PWNf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 848w, https://substackcdn.com/image/fetch/$s_!PWNf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 1272w, https://substackcdn.com/image/fetch/$s_!PWNf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PWNf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png" width="1456" height="829" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:829,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1337271,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/174718954?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PWNf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 424w, https://substackcdn.com/image/fetch/$s_!PWNf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 848w, https://substackcdn.com/image/fetch/$s_!PWNf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 1272w, https://substackcdn.com/image/fetch/$s_!PWNf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e8347c-2d76-467c-8394-f24e2ce803bf_1598x910.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is the full description of the project steps</figcaption></figure></div><p>For the structured output, I asked for a match ID number (or None, if there&#8217;s no good match), a confidence level, and "reasoning&#8221;, or an explanation of the answer. </p><p>For this project, I didn&#8217;t actually use the confidence or reasoning fields for anything. The confidence score isn&#8217;t calibrated&#8212;it hasn&#8217;t been trained against labeled examples, so it&#8217;s just a guess. And the reasoning field isn&#8217;t the model&#8217;s actual decision process, but a post-hoc justification. Both can still be handy for debugging or flagging cases to review.</p><h2><strong>Where I&#8217;ve Used This</strong></h2><p>I&#8217;ve used variations of this pattern for:</p><ul><li><p><strong><a href="https://presentofcoding.substack.com/p/my-text-pipelines-meet-the-real-world">Analyzing public comments</a></strong>: First, discovering what themes people discuss, then classifying each comment using those themes</p></li><li><p><strong>Processing research papers</strong>: Extracting summaries, key contributions, methods used</p></li><li><p><strong>Evaluating synthetic data</strong>: Checking if LLM-generated content meets specific criteria</p></li></ul><p>Same building block, different structure.</p><h2><strong>When It Doesn&#8217;t Work</strong></h2><p>I had one dataset where this pattern just wouldn&#8217;t work with certain providers: I wasn't able to consistently get back the structure I wanted. It worked fine with one model but failed with others. I tried multiple different tools for getting structured output across providers until I gave up and said &#8220;well, I guess I&#8217;m just using this with Ollama,&#8221; which is a tool for running LLMs locally on your own machine.</p><p>But since then I&#8217;ve used this on probably 200,000 documents across a dozen projects, and that&#8217;s the only failure I&#8217;ve gotten. Your mileage will vary with provider and data weirdness. If you see failures&#8212;where models keep breaking your schema despite using structured output&#8212;you can try heavier-duty tools. </p><p>For instance, there&#8217;s <a href="https://python.useinstructor.com/">Instructor</a>, which does both output validation (as opposed to just passing the class to the model) and automatic retries if there are failure. I don&#8217;t use it because I haven&#8217;t needed it, but it&#8217;s out there if you do.</p><p>Also, not every model supports structured output. LiteLLM provides an <a href="https://docs.litellm.ai/docs/completion/json_mode#check-model-support">API endpoint for checking whether a particular model supports it</a>, which is helpful when you&#8217;re trying different models.</p><h2><strong>The Bigger Pattern</strong></h2><p>This structured output technique is part of a bigger pattern: most LLM applications I see aren&#8217;t chatbots or RAG systems. They&#8217;re <strong><a href="https://presentofcoding.substack.com/p/adding-structure-to-your-text-data">document processing pipelines</a></strong> that ask the same questions of many documents.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lHyJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lHyJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!lHyJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!lHyJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!lHyJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lHyJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png" width="398" height="398" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:398,&quot;bytes&quot;:2006214,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/174718954?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lHyJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!lHyJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!lHyJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!lHyJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf1af031-2917-4868-80ae-79313c5952e0_1024x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">You put some documents in, you get some results out</figcaption></figure></div><p>When you need to process a pile of text and extract the same information from each one, this pattern is a good one. Same questions, many documents, structured answers.</p><p>The code for my YouTube matcher is <a href="https://github.com/abigailhaddad/hearings">on GitHub</a> if you want to see the full implementation. But honestly, the pattern above is most of what you need to know. Define your structure, constrain your choices, and let the model do the work.</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Hot Claude Summer ]]></title><description><![CDATA[What I Built and What I Learned]]></description><link>https://presentofcoding.substack.com/p/hot-claude-summer</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/hot-claude-summer</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 15 Sep 2025 12:04:50 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7e986435-9884-4784-a45e-73b422d624c8_1548x1246.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I left my federal government job in May, I wasn&#8217;t sure exactly what I wanted to do next, but I knew I wanted to build something useful. The prior months had been bleak. Projects I&#8217;d worked on felt fragile, like they might not exist after me. One day, I got a message that software I relied on was no longer approved. Then&#8212;poof&#8212;it was deleted from my computer.</p><p>Around that time, I decided to try <a href="https://www.anthropic.com/claude-code">Claude Code</a>, the extension for Claude that runs in your development environment. I&#8217;d been using LLMs for coding since GPT-3.5, but apart from a short-lived experiment with GitHub Copilot, my workflow hadn&#8217;t changed: grab code from ChatGPT or Claude&#8217;s GUI, test it, iterate, paste back in. But I liked Claude, and suddenly I had the time to experiment.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>There were some bumps, and it wasn&#8217;t good at everything, but going from GUI to Claude Code was as big a leap as when I first started using LLMs for coding. It let me build out what I wanted to build.</p><h1><strong>What I Built</strong></h1><p>What took shape this summer was a focus on making federal data more accessible. There&#8217;s a ton of really useful federal data out there that tells a lot of stories, but it&#8217;s not always the easiest to work with.</p><p>My biggest projects were with FedScope data, the official source on federal civil servants, and USAJobs data, which contains most federal job listings. I also worked with budget data&#8212;how much each agency is appropriated by Congress, and how much they&#8217;re obligating to spend&#8212;plus some public comment analysis and a <a href="https://abigailhaddad.github.io/hearings/">demo for the Congressional hackathon</a> that matches committee hearings with their YouTube videos.</p><p>Most of this work was data engineering&#8212;shifting data between locations and formats, like APIs, zipped text files, or Excel workbooks&#8212;and cleaning it up. Some was light web development: sites that might be interactive, but where everything runs in the browser, not on a back end or through a database. Claude Code helped in various ways:</p><ul><li><p>When scraping questionnaires for federal job listings, switching from Selenium to <a href="https://playwright.dev/">Playwright</a> took under half an hour and significantly sped up my scraping.</p></li><li><p>For matching the congressional hearings to YouTube videos, Claude suggested <a href="https://github.com/yt-dlp/yt-dlp">a package for getting YouTube metadata</a> so I could stop using the very rate-limited YouTube API, and then implemented it.</p></li><li><p>Across all of this, Claude hardened pipelines with logging, error handling, and small things like <a href="https://www.theapplegeek.co.uk/blog/caffeinate">caffeinate</a> to keep my laptop awake overnight.</p></li></ul><p>Not everything landed. I tried it for slides and data analysis, with much less success. It can draft slides, but I rewrite all of them. And its instincts for data visualization when asked to analyze a data set or even answer specific questions are terrible: overcomplicated charts, unreadable outputs, zero intuition for what the data is about.</p><p>Still, the sheer volume of what I was able to build&#8212;quickly, and in new domains&#8212;was different from anything I&#8217;d done before.</p><h1><strong>Bubble Charts and Bubble Math</strong></h1><p>Here&#8217;s one example of attempting something new. I needed to visualize budget data: agency, amount of funds appropriated, and the percentage of those appropriated funds which had been obligated.</p><p>Pre-LLMs, I&#8217;d have reached for the Python <a href="https://plotly.com/">plotly</a> package. If I was feeling ambitious, I might have tried Dash, the tool for making plotly figures into interactive dashboards. With LLMs, I might have worked in JavaScript, but I would still have felt constrained. With Claude Code, I started from a different premise and therefore a different question: I can build whatever visualization I want. What&#8217;s the best way to show the data?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-Bl7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-Bl7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 424w, https://substackcdn.com/image/fetch/$s_!-Bl7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 848w, https://substackcdn.com/image/fetch/$s_!-Bl7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 1272w, https://substackcdn.com/image/fetch/$s_!-Bl7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-Bl7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png" width="1456" height="586" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:586,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:780083,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/173483027?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-Bl7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 424w, https://substackcdn.com/image/fetch/$s_!-Bl7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 848w, https://substackcdn.com/image/fetch/$s_!-Bl7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 1272w, https://substackcdn.com/image/fetch/$s_!-Bl7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f81cbd2-2f80-4b0c-a7d4-765707a573e7_2730x1098.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is a bubble chart</figcaption></figure></div><p>That led to an interactive D3 bubble chart with multiple aggregation levels and filters responsive to user selections&#8212;built in one evening. And I don&#8217;t know JavaScript even a little. Initially, I also tried a two-color scheme for the inside and outside of the bubble using different colors for agency vs. subagency, but it was too busy, so I scrapped it. The luxury was being able to try and discard experiments so quickly.</p><p>A week later, I noticed some bubbles weren&#8217;t placed correctly on the x-axis. Bubble math is its own rabbit hole: balancing accurate placement on the x-axis against minimizing overlap. I ended up writing a grid search optimization for bubble parameters. It&#8217;s not good yet, and I may never fix it&#8212;but I wouldn&#8217;t even have thought to try before.</p><p>These are the problems I want to work on: showing complicated data clearly, not wrestling with syntax.</p><h1><strong>What Makes This Different</strong></h1><p>Claude Code lives in your environment. It sees everything&#8212;file structure, error messages, git state&#8212;and can act across it. That volume of context dwarfs what I&#8217;d copy-paste into a GUI.</p><p>Take minor refactoring: Claude can rename files, create folders, move things around, and update paths. I&#8217;d never bother doing that with an LLM if I had to copy and paste everything in. Or git errors: I used to debug them via Google and self-loathing. Now Claude fixes them, and sets up GitHub Actions I wouldn&#8217;t have attempted before. Suddenly, improvements are cheap.</p><p>Another difference is that programming almost feels social. It&#8217;s more like coding with someone&#8212;like a rubber duck that talks back. So part of why I built more was that I spent more time doing it. I&#8217;ve always had the &#8220;I&#8217;ll be done debugging this soon&#8221; problem, where you look up and it&#8217;s an hour later. Claude Code made it worse because it made coding more engaging.</p><p>This heat map with my git commits&#8212;not all of them, but most&#8212;is an example of something I never would have spun up without Claude Code. But experimenting with visualizations of git commits for a blog post becomes totally reasonable when it takes 15 minutes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HQID!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HQID!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 424w, https://substackcdn.com/image/fetch/$s_!HQID!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 848w, https://substackcdn.com/image/fetch/$s_!HQID!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 1272w, https://substackcdn.com/image/fetch/$s_!HQID!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HQID!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png" width="396" height="461.3808630393996" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1242,&quot;width&quot;:1066,&quot;resizeWidth&quot;:396,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HQID!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 424w, https://substackcdn.com/image/fetch/$s_!HQID!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 848w, https://substackcdn.com/image/fetch/$s_!HQID!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 1272w, https://substackcdn.com/image/fetch/$s_!HQID!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37c3439e-f232-42b2-92f2-6aa4686af1e1_1066x1242.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I don&#8217;t know why I&#8217;m not committing code Wednesday nights.</figcaption></figure></div><h1><strong>Where It Fails</strong></h1><p>Like LLMs in general, Claude Code is strong on well-documented patterns&#8212;D3 charts, git parsing, GitHub Actions&#8212;but weak on data intuition and messy, real-world problems. I spent a day guiding it through a slightly novel dataset I already knew the answer to, just to see if it could reason its way there. It never got close, and it kept insisting it had solved it.</p><p>Budget data was another case: I went in circles until I realized the problem was that my obligations data had real dates, while outlays&#8212;the actual spending&#8212;was cumulative, a snapshot from whenever I pulled it. Claude Code was never going to figure that out.</p><p>And even when it&#8217;s on the right track, it creates its own headaches: spawning new scripts instead of editing existing ones, sprinkling in try-catch blocks and functionality I never asked for and didn&#8217;t want.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PKo0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PKo0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 424w, https://substackcdn.com/image/fetch/$s_!PKo0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 848w, https://substackcdn.com/image/fetch/$s_!PKo0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 1272w, https://substackcdn.com/image/fetch/$s_!PKo0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PKo0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png" width="516" height="452.5631868131868" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/efafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1277,&quot;width&quot;:1456,&quot;resizeWidth&quot;:516,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PKo0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 424w, https://substackcdn.com/image/fetch/$s_!PKo0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 848w, https://substackcdn.com/image/fetch/$s_!PKo0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 1272w, https://substackcdn.com/image/fetch/$s_!PKo0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefafaae7-b08a-4794-9f2f-7307def8fc40_1600x1403.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">These are the system instructions I wrote for Claude. It follows some of the instructions. Others, it entirely ignores.</figcaption></figure></div><p>The hardest failures came from deploying. I&#8217;d never launched websites before&#8212;let alone ones that updated automatically with new data&#8212;and every small break felt urgent, something I had to fix immediately no matter the time or what else I was doing. The problem was that building faster than I was learning how to test or maintain. Some of that was the speed Claude Code enabled; some of it was just side projects turning into tools. Eventually, I set up a more professional workflow for my sites with automated data updates: separate branches, and no more pushing to production without passing tests. Claude Code helped me get there, too.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1J63!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1J63!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 424w, https://substackcdn.com/image/fetch/$s_!1J63!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 848w, https://substackcdn.com/image/fetch/$s_!1J63!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 1272w, https://substackcdn.com/image/fetch/$s_!1J63!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1J63!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png" width="507" height="380.4696707105719" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:433,&quot;width&quot;:577,&quot;resizeWidth&quot;:507,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1J63!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 424w, https://substackcdn.com/image/fetch/$s_!1J63!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 848w, https://substackcdn.com/image/fetch/$s_!1J63!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 1272w, https://substackcdn.com/image/fetch/$s_!1J63!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff53a6162-5f87-43d0-8fcf-6d2f9d9f3006_577x433.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1><strong>What This Means</strong></h1><p>I&#8217;ve never liked low-code or no-code tools. They put you in a box&#8212;you can only build what someone else already implemented. Claude Code is the opposite. It opens boxes. It let me try frameworks, languages, and approaches I never would have touched before.</p><p>People sometimes cite <a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/">the METR study to me</a>, showing Claude Code didn&#8217;t help software developers much. I don&#8217;t know why I had such a different experience. My best guess is that it&#8217;s because in that study, developers were working on codebases they already knew well. For me, the value was mostly not that: Claude let me try things I otherwise wouldn&#8217;t have. Also, I&#8217;m not a software developer.</p><p>I am trying to retrain myself to slow down, look at the data more, and reinvest saved time in testing. It&#8217;s hard.</p><p>But even so: I&#8217;m grateful. I had this summer to choose what to build and put in the hours to do it. Now people email me asking for data. I start a new job soon, and I don&#8217;t know how I&#8217;ll keep it going. But that&#8217;s a good problem to have&#8212;and Claude Code is part of why I have it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Getting USAJobs Data]]></title><description><![CDATA[And how to store it once you have it]]></description><link>https://presentofcoding.substack.com/p/getting-usajobs-data</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/getting-usajobs-data</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 01 Sep 2025 12:00:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FQsO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>USAJobs is where the federal executive branch lists most of its job openings&#8212;with some legislative and judicial branch jobs as well. The executive branch doesn't post every job there, but if you're trying to get data on what the government is trying to hire for, or what it tried to hire for previously, USAJobs is the place to go.</p><p>This post covers how to programmatically access that data. Sometimes it&#8217;s easy, sometimes it&#8217;s not. Want to know how many jobs an agency has listed by <a href="https://presentofcoding.substack.com/i/153664235/a-quick-note-about-occupational-series-and-job-title">occupational code</a> right now? Sign up for an API key, make one request, and you're done. Want to know the qualifications for every job listed in the last year? You'll spend a few days scraping data, and then you&#8217;ll have to figure out how to parse it correctly. </p><blockquote><p><strong>USAJobs is job listing data, not hiring data. </strong>A single posting might result in zero hires, one hire, or multiple hires. There's a Total Positions field that shows how many people the agency wants to hire, but it might have a value of &#8220;few&#8221; or &#8220;many&#8221;. There's also a Position Offering Status field that tracks whether a job is open, closed, or has made selections. But "selections made" just means the agency picked someone&#8212;not how many, and not that those people said yes or started working. If you need data on who was hired (not just what was posted), you'll want FedScope, which I'll cover later.</p></blockquote><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong>Three Ways to Get the Data</strong></h2><p>There are three general ways to get the data: the Historical Jobs API, the Current Jobs API, and web scraping. You can also scrape most of the <a href="https://www.opm.gov/services-for-agencies/recruiting-staffing-solutions/assessment-questionnaires/">assessment questionnaires</a>.</p><h3><strong>1. Historical Jobs API: Goes Back Far, Limited Fields</strong></h3><p>The <a href="https://developer.usajobs.gov/api-reference/get-api-historicjoa">Historical Jobs API</a> has fields like job title, department and agency, opening and closing date, occupational series, location, pay grade, and salary range. What it doesn&#8217;t have is any of the rich unstructured text data in the listing, like duties or qualifications, which are in the Current Jobs API.</p><p>The fields here are a subset of what&#8217;s in the Current Jobs API, except for the Position Offering Status field.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> </p><p>You can pull comprehensive data by making an API call for each day. No API key is needed.</p><p><strong>Data coverage note:</strong> While there are some earlier postings, the data is extremely sparse until March 2017. </p><h3><strong>2. Current Jobs API: Easy and Detailed</strong></h3><p>The Current Jobs API gives you active job postings with the structured data fields, plus all the rich text content: duties, education requirements, qualification requirements, how to apply instructions, etc.</p><p>The first catch: 10,000 result cap per query, and you can only query the previous x days (not specific dates). To get everything currently posted, slice queries by agency or occupation to stay under the 10,000 limit. </p><p>The other catch: once the job is no longer current, it won&#8217;t be in that API anymore and if you want the good text data, you&#8217;re going to have to scrape it. </p><p>To use the API, you&#8217;ll need an <a href="https://developer.usajobs.gov/apirequest/">API key from developer.usajobs.gov</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FQsO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FQsO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 424w, https://substackcdn.com/image/fetch/$s_!FQsO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 848w, https://substackcdn.com/image/fetch/$s_!FQsO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 1272w, https://substackcdn.com/image/fetch/$s_!FQsO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FQsO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png" width="1220" height="678" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/977bd029-5090-473c-9399-fe6924295467_1220x678.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:678,&quot;width&quot;:1220,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:422018,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/172352515?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FQsO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 424w, https://substackcdn.com/image/fetch/$s_!FQsO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 848w, https://substackcdn.com/image/fetch/$s_!FQsO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 1272w, https://substackcdn.com/image/fetch/$s_!FQsO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977bd029-5090-473c-9399-fe6924295467_1220x678.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://parkhiring.netlify.app/">This</a> is based on both the Current and Historical Jobs API.</figcaption></figure></div><h3><strong>3. Scraping: Everything, But It&#8217;s Complicated</strong></h3><p>Need full content for jobs that are no longer current, or something that&#8217;s on the listing but not in either API? You're in scraping territory. This gets you everything that's publicly available on that listing page.</p><p>First, get job IDs from one of the APIs. Then construct URLs like:</p><pre><code>https://www.usajobs.gov/job/[job-id]</code></pre><p>The issues with scraping include:</p><ul><li><p><strong>Speed:</strong> Took me ~24 hours for four months of data. It&#8217;s tempting to get aggressive with parallelization, but they will block you</p></li><li><p><strong>Inconsistent HTML: </strong>Fields like "Qualifications" vary across listings</p></li><li><p><strong>Storage: </strong>Full HTML files are huge&#8212;convert to text when possible</p></li><li><p><strong>Historical limits: </strong>Need job IDs from APIs to construct URLs&#8212;can't scrape without those</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!W4gv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W4gv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 424w, https://substackcdn.com/image/fetch/$s_!W4gv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 848w, https://substackcdn.com/image/fetch/$s_!W4gv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 1272w, https://substackcdn.com/image/fetch/$s_!W4gv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W4gv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png" width="548" height="252.5467032967033" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:671,&quot;width&quot;:1456,&quot;resizeWidth&quot;:548,&quot;bytes&quot;:465891,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/172352515?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!W4gv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 424w, https://substackcdn.com/image/fetch/$s_!W4gv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 848w, https://substackcdn.com/image/fetch/$s_!W4gv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 1272w, https://substackcdn.com/image/fetch/$s_!W4gv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7e8ee0-9cc5-45f5-b008-7ea76f69bfd5_1650x760.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I recently used scraping to find mentions of direct hire </figcaption></figure></div><p>Even if you are scraping, you should still get everything you can from the API instead of trying to parse it from the HTML.</p><h4><strong>Bonus: Assessment Questionnaires</strong></h4><p>Many federal jobs require applicants to fill out assessment questionnaires. If you need to analyze the actual content of these questionnaires, you're looking at a bit more complexity.</p><p>Most questionnaires are hosted on USAStaffing or Monster Government.</p><p>Monster Government questionnaires can be scraped with regular HTTP requests after <a href="https://github.com/abigailhaddad/usajobs_historical/blob/main/questionnaires/extract_questionnaires.py#L156-L164">transforming the URL format</a>. USAStaffing requires a browser emulator like Playwright due to dynamic loading.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2E0Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2E0Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 424w, https://substackcdn.com/image/fetch/$s_!2E0Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 848w, https://substackcdn.com/image/fetch/$s_!2E0Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 1272w, https://substackcdn.com/image/fetch/$s_!2E0Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2E0Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png" width="1456" height="402" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:402,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:442228,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/172352515?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!2E0Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 424w, https://substackcdn.com/image/fetch/$s_!2E0Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 848w, https://substackcdn.com/image/fetch/$s_!2E0Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 1272w, https://substackcdn.com/image/fetch/$s_!2E0Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6675d94-5cf1-481a-8c13-900083cf138d_2830x782.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://federalhiringessays.netlify.app/">This is what I built</a> with the questionnaire data</figcaption></figure></div><p>I haven't tried to find the other sites that questionnaires are hosted on in order to scrape them, but if you know of any and want me to try, let me know.</p><h2><strong>Tips for Working with the APIs</strong></h2><ul><li><p><strong>Pagination:</strong> Make sure you're getting multiple pages for longer queries. The Historical Jobs API returns a continuation URL (check for paging.next in the response) that you follow until it's null. The Current Jobs API uses page numbers&#8212;increment the Page parameter until you get no more results.</p></li><li><p><strong>Search limitation:</strong> You cannot query by job ID in either API (the USAJOBSControlNumbers/MatchedObjectId). You have to use other fields like date ranges or agencies to find jobs, then extract the job IDs from the results.</p></li><li><p><strong>Data gaps:</strong> If a listing is just a front page for applying elsewhere, those fields won't be complete in the API either. </p></li><li><p><strong>Deduplication and field harmonization: </strong>There is significant overlap between both APIs&#8212;there are current jobs in the Historical Jobs API&#8212;so if you want both, you will have to deduplicate. And since the two APIs use completely different field names for the same data, and in some cases format data differently, you&#8217;ll also need to <a href="https://datawrapper.dwcdn.net/sTR3j/1/">harmonize the fields</a>.</p></li></ul><h2>Examples of Data Approaches</h2><p>There are several different approaches you might take, depending on the problem you&#8217;re trying to solve. Here are a few examples:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/YXCLF/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8b1c1f66-0075-4f0d-bd9c-6378ec4aa458_1220x1112.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/043a8900-7c9e-4b69-9d15-c4ca0bde2e60_1220x1182.png&quot;,&quot;height&quot;:594,&quot;title&quot;:&quot;Data Approaches by Question&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/YXCLF/1/" width="730" height="594" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><h2><strong>Data Storage Decisions</strong></h2><p>Your storage and structure decisions flow from what you're trying to accomplish.</p><p>My approach: Since the Current and Historical Jobs APIs have different fields&#8212;with the current one containing rich text content that doesn't exist in the historical one&#8212;I couldn't harmonize them into one schema without losing data. But I still wanted to query across both datasets. So I keep all raw data from both APIs and create overlay fields for the parts that overlap. This preserves all the rich content from the Current Jobs API while allowing queries across both datasets. <strong>It&#8217;s messy&#8212;this is the kind of structure I&#8217;d never choose unless I really needed to keep everything.</strong></p><p>File format: I use Parquet files because I'm hosting everything on GitHub using Large File Storage (LFS), and file size really matters for staying within free tier limits. Parquet compresses incredibly well&#8212;better than CSV or JSON&#8212;making it feasible to share years of federal job data. Plus, Parquet works great with pandas and DuckDB, and handles nested API structures without flattening.</p><p>Here are a few other examples:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/3UMbF/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34d59384-5ae2-4c21-9612-69e1652a63f8_1220x812.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/59a93fda-ee3f-46b7-b347-48a34d0298d2_1220x882.png&quot;,&quot;height&quot;:430,&quot;title&quot;:&quot;Storage Approaches by Use Case&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/3UMbF/1/" width="730" height="430" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><h2><strong>Other Data Sources</strong></h2><p>While USAJobs captures the vast majority of federal civilian listings, there are a few other places to look depending on what you need:</p><ul><li><p><strong><a href="https://www.fedscope.opm.gov/">FedScope</a></strong>: Shows what agencies actually hired (as opposed to what they posted), but it's released with significant delays due to federal hiring timelines and processing time. It also lacks the detailed job-level information you get from USAJobs: you can get occupational code, location, grade, agency, and supervisory status, but not anything like duties.</p></li><li><p><strong><a href="https://www.govinfo.gov/collection/plum-book">PLUM book</a></strong>: The Policy and Supporting Positions book lists political appointments. It has traditionally been published every four years after presidential elections, though recent legislation now requires annual updates.</p></li><li><p><strong>Federal Hiring Dashboard</strong>: <a href="https://www.opm.gov/policy-data-oversight/federal-hiring-and-selection-outcome-dashboard/">The Federal Hiring and Selection Outcome Dashboard</a> provides some information on hiring outcomes, but there's no raw data available for download and the most recent data is from June.</p></li><li><p><strong>Federal Hiring Assessments and Selection Outcome Dataset</strong>: <a href="https://catalog.data.gov/dataset/federal-hiring-assessments-and-selection-outcome-dataset">Additional hiring outcomes data</a>. The data is extensive, but it hasn't been updated since FY 2024.</p></li><li><p><strong>Contractor positions</strong>: There isn't a centralized source for contractor positions. This is a really difficult problem to solve.</p></li></ul><div><hr></div><p>Most of my USAJobs code is <a href="https://github.com/abigailhaddad/usajobs_historical">available here</a>, but this repo doesn't do scraping: get in touch if you want access to my scraping repo. And if you build something interesting with this data, I'd love to hear about it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>There also used to be a "how many applications did you get?" field in the Historical Jobs API. Agencies didn&#8217;t have to populate it and it only had the number of people who started, not completed, the application. With the most recent Historical Jobs API redo, it is no longer present at all.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Government Document Analysis]]></title><description><![CDATA[What AI Has Made Easier and What It Can&#8217;t Fix]]></description><link>https://presentofcoding.substack.com/p/government-document-analysis</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/government-document-analysis</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 04 Aug 2025 12:01:54 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/972f6a4a-b3dd-4bce-b333-53200f8a12df_320x213.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently <a href="https://schedule-f.vercel.app/page/1/size/10">analyzed 35,000 public comments on "Schedule F"</a>&#8212;a proposed regulation to strip civil service protections from many government workers&#8212;using large language models. The project illustrates where AI genuinely helps and where we're still stuck with fundamental problems of user design and data collection, as well as security and procurement constraints.</p><h2><strong>What AI Made Easier</strong></h2><p>When agencies propose certain types of new regulations, they're required to collect and respond to public comments. The idea is that agencies should address all substantive arguments being made. But when there are tens of thousands of comments or more, manual analysis becomes difficult and expensive.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Before large language models, automating this analysis was severely limited. You could search for keywords or use smaller models to cluster similar comments and identify topics. But these methods struggle with varied wording or complicated arguments.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GMNE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GMNE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 424w, https://substackcdn.com/image/fetch/$s_!GMNE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 848w, https://substackcdn.com/image/fetch/$s_!GMNE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 1272w, https://substackcdn.com/image/fetch/$s_!GMNE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GMNE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png" width="1456" height="741" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:741,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GMNE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 424w, https://substackcdn.com/image/fetch/$s_!GMNE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 848w, https://substackcdn.com/image/fetch/$s_!GMNE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 1272w, https://substackcdn.com/image/fetch/$s_!GMNE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11221147-d7f6-468c-b786-15edcfa70f31_1600x814.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is the proposed rule that I analyzed the comments on</figcaption></figure></div><p>Large language models do much more. You can more reliably categorize comments as agree/disagree and identify very granular themes, even when the wording varies widely. Multimodal models like <a href="https://cloud.google.com/vertex-ai/generative-ai/docs/samples/generativeaionvertexai-gemini-pdf">Gemini</a> also improve processing attachments. They can extract text from scanned PDFs, images, and other documents that were previously difficult to handle automatically.</p><p>For Schedule F, I processed 35,000 comments through OpenAI's cheapest model for under $20. Processing attachments through Gemini cost under a dollar for files that failed to process locally using other tools. It didn't work on all of them, but it was a big improvement from previous models. This was fast, cheap, and good&#8212;and it could be better with more time and evaluation, while still being much faster and cheaper than human analysis.</p><p>This example represents processing unstructured text data, or a workflow where <a href="https://presentofcoding.substack.com/p/adding-structure-to-your-text-data">we want to ask the same questions of every document</a>. In these comments, I was looking for a specific set of themes, a representative quote, and agree/disagree categorization. For other types of documents, we'd be asking different questions.</p><p>LLMs represent a genuine advance in data processing capabilities. Organizations have tons of documents that have become much easier to analyze. I saw a tiny fraction of the possible use cases when I was a machine learning engineer at DHS, but they're endless.</p><h2><strong>The Bigger Win: Fixing Data Collection Upfront</strong></h2><p>But what's better than processing unstructured data? Not having to process unstructured text data because you were able to collect structured data upfront.</p><p>For comment data, the government could improve data collection in two ways.</p><p>First, instead of accepting any type of file attachment, uploading files could be limited to text documents, Word documents, or non-scanned PDFs. Some of the attachments people send are truly not readable in any way, like dark, scanned PDFs. <strong>It's not good user interface design to accept attachments we can&#8217;t use.</strong></p><p>Second, in addition to allowing raw data (in attachments or not), agencies could add a field where they ask users to summarize their comment or say the most important thing. Where it makes sense, they could add an approve/reject selection button.</p><p>However, there are still many cases where data is inherently unstructured, and so you&#8217;re stuck parsing it if you want to understand it. For instance, if you're analyzing emails to determine how to respond to Freedom of Information Act (FOIA) requests, the unstructured nature of that email data is unavoidable.</p><h2><strong>Better Interfaces for Existing Data</strong></h2><p>Better interfaces are another non-AI way to make data more accessible. For instance, the easiest way to get public comment data is to fill out a form and get a massive spreadsheet (CSV) file that does not contain the text of the attachments. It's great that this exists. But even without any AI, it would be straightforward to build frontends to make the data easier to search, including the attachments.</p><p>This applies to much government data. Either it lacks programming interfaces (APIs) and the front ends are difficult or limited, like FedScope data (which is currently getting a redesign). Or like USAJobs data, where there's no graphical interface for historical data. Additionally, if you want any of the rich text data, like job duties or requirements, you can't get it from the API at all &#8212; you're going to be scraping inconsistent web data.</p><p>People struggle to access information that's technically public and available, and that&#8217;s a problem. There's a lot of room for the government and non-governmental groups to build out tooling to make data more accessible.</p><p>This is also an issue within government, where a lot of data also gets passed via spreadsheet. It could be more accessible (and version-controlled!) if it lived in a central repository with some basic table functionality.</p><h2><strong>Harder to Build From the Inside</strong></h2><p>When I was a DHS employee, I wanted to build tooling to analyze public comments. But if I'd gotten the go-ahead for it, I would have found it more challenging than on the outside. This was true even though I did sometimes have access to LLM APIs, so I could query LLMs like the one I used for my text processing&#8212;which many technical employees within government don&#8217;t have, including ones with clear use cases for it. </p><p>But outside of DHS, I can also use whatever coding assistants I want to help with coding&#8212;like <a href="https://www.anthropic.com/claude-code">Claude Code</a>, which I used for this project. Coding assistants are enormously useful to me because they integrate into my system directly. But even though the comments data was public, there are no coding assistants I could have used at DHS: I would have been copying and pasting code between my computer and the available LLM, which is a much worse way of using LLMs in coding.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VIVf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VIVf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 424w, https://substackcdn.com/image/fetch/$s_!VIVf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 848w, https://substackcdn.com/image/fetch/$s_!VIVf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 1272w, https://substackcdn.com/image/fetch/$s_!VIVf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VIVf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png" width="456" height="341.42713567839195" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:894,&quot;width&quot;:1194,&quot;resizeWidth&quot;:456,&quot;bytes&quot;:410547,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/169525950?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VIVf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 424w, https://substackcdn.com/image/fetch/$s_!VIVf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 848w, https://substackcdn.com/image/fetch/$s_!VIVf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 1272w, https://substackcdn.com/image/fetch/$s_!VIVf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe869af24-4f6c-4b6b-a1f9-081c7995c25b_1194x894.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I haven&#8217;t used Claude Code&#8217;s competitors, so I don&#8217;t know how they compare&#8212;but this has been my experience with it.</figcaption></figure></div><p>I get that there's a balance here between security and access. But the balance now is one of too much risk aversion: in government, you never get in trouble for saying no to new technology. Because of this, there is not enough urgency around making sure that civil servants have access to the best tooling, even if it's inexpensive enough that we're using it for our side projects.</p><h2><strong>Evaluation and Trust</strong></h2><p>In contrast to a lot of narratives, I think AI actually provides an opportunity for more transparency&#8212;but that doesn't happen automatically.</p><p>For instance, I didn't get every comment categorized correctly.</p><p>But you can see what prompts I used to categorize it, because <a href="https://github.com/abigailhaddad/schedule_f">they're on GitHub</a>. You can see the evaluation frameworks I built and discarded, because they're in the git history. If I'd categorized this manually in a spreadsheet, I still wouldn't have gotten it perfect. And you wouldn't get any insight into the process.</p><p>As the government uses these tools, I think it's important that at a minimum they live on internal code repositories. This is as opposed to proprietary/drag-and-drop interfaces where it's difficult for even the government clients&#8212;the people the models are being built for&#8212;to see exactly what happened. And when possible, code should be open-sourced for the public to see it.</p><p>And regardless of whether it&#8217;s appropriate to open-source the code, you should at least be able to share some info about your evaluation framework. <a href="https://govwhitepapers.com/whitepapers/implementation-of-dhs-directive-026-11-use-of-face-recognition-and-face-capture-technologies">The 2024 Report on Select Use Cases of Face Recognition and Face Capture Technology from DHS</a> was a good example of this.</p><p>AI isn't magic&#8212;it's a useful tool in some circumstances and the wrong answer in others. Our job as technologists is to work with users to determine what they need and to provide transparency so stakeholders can make informed decisions. But the government should give their employees and contractors the technical infrastructure to do that well.</p><div><hr></div><p><em>A version of this appeared at <a href="https://reformforresults.org/reform-for-results-working-group-publications/">Reform for Results</a>. </em></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[How to use machine translation responsibly in government]]></title><description><![CDATA[This was originally posted on FedScoop.]]></description><link>https://presentofcoding.substack.com/p/how-to-use-machine-translation-responsibly</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/how-to-use-machine-translation-responsibly</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Mon, 28 Jul 2025 12:03:02 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fedbf2fc-bfbf-41ad-9c00-692ae3152e7f_832x718.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>This was originally posted on <a href="https://fedscoop.com/how-to-use-machine-translation-responsibly-in-government/">FedScoop</a>. </em></p><p>The Department of Justice recently <a href="https://www.nextgov.com/digital-government/2025/07/justice-pushes-agencies-use-ai-assisted-translations-when-offering-them-all/406776/#:~:text=The%20push%20to%20use%20artificial,that%20have%20limited%20English%20proficiency.">issued guidance</a> encouraging federal agencies to use "artificial intelligence and machine translation to communicate with individuals who are limited English proficient." The memo specifically calls for "responsible use" of these technologies to "produce cost-effective methods for bridging language barriers."</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>But the memo provides no details on what "responsible use" means. There's also little guidance in <a href="https://www.whitehouse.gov/wp-content/uploads/2025/02/M-25-21-Accelerating-Federal-Use-of-AI-through-Innovation-Governance-and-Public-Trust.pdf">memo M-25-21</a> on Accelerating Federal Use of AI &#8212; or the <a href="https://fedscoop.com/trump-rescinds-biden-ai-order-creates-doge-orders-in-person-work/">revoked Biden AI executive order</a> &#8212; regarding responsible use for translation models specifically. This leaves agencies to figure out implementation details on their own.</p><h2>So, what does responsible AI translation look like?</h2><p>Responsible use of machine translation requires use-case specific evaluation both prior to and subsequent to deployment, as well as using those results to inform what happens. Here's what agencies should do":</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FxV8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FxV8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FxV8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FxV8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FxV8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FxV8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg" width="516" height="445.2980769230769" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:718,&quot;width&quot;:832,&quot;resizeWidth&quot;:516,&quot;bytes&quot;:199661,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://presentofcoding.substack.com/i/169375116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FxV8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FxV8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FxV8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FxV8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a40a24a-2d74-4118-a6b5-0dc8c7c03525_832x718.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Test on your content for your specific use cases. </strong>Don't rely on general model performance benchmarks. Create representative samples of the documents for each of your use cases. A tool that works well for routine correspondence might fail on technical documents.</p><p><strong>Compare all your options for each use case. </strong>Test multiple machine translation systems against human translators. Have qualified evaluators rate translations. In addition to needing different samples for each use case, you might also need different evaluation criteria or cut-off scores. Evaluation doesn&#8217;t just show how often models fail, but also in which circumstances &#8212; information that can shape your deployment plans.</p><p><strong>Act based on the results. </strong>You might find that machine translation works well for some languages but not others, or that using uncertainty scores to flag low-confidence translations for human review works better than an all-or-nothing approach. Though confidence scoring is trickier here than with some other models, it's something you can pursue.</p><p><strong>Continue evaluating after deployment. </strong>Your documents and needs will evolve. Regular re-evaluation with a subset of new documents ensures the model continues to meet your requirements.</p><h2>The real problem: deployment without evaluation</h2><p>My primary concern is that agencies will deploy machine translation tools with minimal testing, relying on vendor claims or general benchmarks that may not apply to their specific use cases. The government didn't have enough technical expertise prior to President Donald Trump&#8217;s inauguration, and it's only gotten worse since. And even when contractors are doing the work, federal government civilians are ultimately the ones responsible for vendor selection, contract wording, and what deliverables to request.</p><p>During my time as an AI/ML engineer at the Department of Homeland Security&#8217;s <a href="https://fedscoop.com/tag/dhs-ai-corps/">AI Corps</a> &#8212; where I drafted a guide on test and evaluation for AI/ML models &#8212; I saw tremendous variance across government, from agencies with well-informed evaluation plans that asked all the right questions about model performance to teams that couldn&#8217;t do proper evaluation because the government wasn&#8217;t giving them access to post-deployment data. I expect implementation of the DOJ guidance will be similarly inconsistent &#8212; some agencies will conduct thorough evaluations while others will deploy tools with minimal testing.</p><h2>More rules aren&#8217;t the answer, either</h2><p>But to the skeptics of machine translation, I also have a message: Even now, agencies aren't always choosing between machine translation and good human translation. In some cases, they're choosing between unevaluated machine translation and none at all, where documents just don't get translated, or translated in a timely way.</p><p>For instance, at a federal agency I worked with, employees were using Google Translate for somewhat sensitive material. A secure machine translation tool with even basic evaluation would have solved both the security problem and supplied more information about what types of documents were fine to machine translate versus which needed human review.</p><p>Additionally, evaluation standards should be driven by use case requirements, not the technology being used. While a focus on AI evaluation is important, this same attention to performance standards should apply regardless of whether work is done by humans, machines, or via hybrid approaches.</p><p>Finally, the lack of specific implementation guidance from both this White House and the previous one is appropriate. More prescriptive requirements wouldn't solve the underlying capacity problems &#8212; but they would be interpreted in some agencies in the most restrictive ways possible. For instance, a White House memo requiring evaluation of machine translation models could easily be <a href="https://www.niskanencenter.org/ai-meets-the-cascade-of-rigidity/">interpreted at lower levels</a> as requiring that this evaluation happen prior to allowing technologists to so much as install an open-source language model and try it out. And meanwhile, documents aren&#8217;t getting translated at all &#8212; or they&#8217;re getting sent to Google Translate.</p><p>So even as an evaluation advocate, I don't see the guidance's vagueness as the problem. When agencies stumble on machine translation deployment, it'll be because of lack of institutional capacity, and that wouldn't be fixed by being told to do evaluation.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Actually, LinkedIn is Fine]]></title><description><![CDATA[Here&#8217;s How to Use It]]></description><link>https://presentofcoding.substack.com/p/actually-linkedin-is-great</link><guid isPermaLink="false">https://presentofcoding.substack.com/p/actually-linkedin-is-great</guid><dc:creator><![CDATA[Abigail Haddad]]></dc:creator><pubDate>Tue, 15 Jul 2025 12:02:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!eapR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Everyone loves to hate LinkedIn. There's a popular subreddit called <a href="https://www.reddit.com/r/LinkedInLunatics/">LinkedIn Lunatics</a> dedicated to mocking the platform's most cringe-worthy posts: the humble-bragging, the fake vulnerability, the performative positivity that makes you want to throw your laptop out the window.</p><p>But here's the thing: LinkedIn might actually be useful to you professionally. And you don't have to do any of that stuff to get value from it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong>LinkedIn Solves Real Problems</strong></h2><p>A lot of career-related problems are actually information problems. What roles should I apply for? What's happening in my field that I should keep up with? Who are the people with the skills and interests I'm looking for to fill roles at my organization?</p><p>I know "networking" feels gross and transactional to many people. But there's no master directory for any of this information. You use what's available. LinkedIn isn't perfect, but it's often the most efficient option. Here are a few things it can do for you:</p><ul><li><p><strong>Discovery</strong>: See what people in your field are talking about, find tools you didn't know existed, learn about events you might want to attend.</p></li><li><p><strong>Visibility</strong>: Let people know what you're working on, interested in, or thinking about&#8212;and if you're job searching.</p></li><li><p><strong>Messaging</strong>: People can find and contact you about opportunities, and you can reach out when you need information or introductions.</p></li></ul><p>I've learned about tools I later used from LinkedIn first. I've reconnected with people I'd lost touch with. My last job? I applied because I saw people talking about it on LinkedIn. And the one before, I found because a recruiter messaged me on LinkedIn&#8212;and I wasn&#8217;t at all active then, beyond having an up-to-date profile.</p><h2><strong>Legibility Without Cringe</strong></h2><p>Yes, there are LinkedIn posts that make you cringe. There's an algorithm, and some things that perform well are kind of gross. But lots of posts aren't that. Some are just&#8230; fine.</p><p>Things I've seen in my feed recently include:</p><ul><li><p>"Everyone says 'We want the best people.' But your hiring process still looks like this."</p></li><li><p>"Gov agencies hate risk. Prove your solution works small before going big."</p></li><li><p>"Want to learn Rust with me? I'm teaching a workshop at Cascadia R Conference in June."</p></li><li><p>"What's your unpopular opinion about AI careers? I'll go first: Most AI jobs don't need deep learning."</p></li></ul><p>None of these are super clickbaity. But they're legible. That is, they answer the question <em>"Why should I care?"</em> right up front. Instead of making people work to figure out what you're talking about, they&#8217;re making it easy for you to decide whether to engage.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eapR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eapR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 424w, https://substackcdn.com/image/fetch/$s_!eapR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 848w, https://substackcdn.com/image/fetch/$s_!eapR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 1272w, https://substackcdn.com/image/fetch/$s_!eapR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eapR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png" width="412" height="514.5992217898832" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1284,&quot;width&quot;:1028,&quot;resizeWidth&quot;:412,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eapR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 424w, https://substackcdn.com/image/fetch/$s_!eapR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 848w, https://substackcdn.com/image/fetch/$s_!eapR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 1272w, https://substackcdn.com/image/fetch/$s_!eapR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F535d9a70-390e-409f-922a-6a9c507c1114_1028x1284.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is a good post because you can tell quickly whether you&#8217;re interested, and the image plus the text work together</figcaption></figure></div><p>Here are some examples of my own posts that follow this principle:</p><p><strong>Sharing useful resources:</strong></p><ul><li><p>"Want raw FedScope data? Can't get it? Check out my git repo."</p></li><li><p>"&#128202; FedScope Employment data is the official dataset on federal government personnel. I'm trying to make it easier to use."</p></li></ul><p><strong>Asking for technical help:</strong></p><ul><li><p>"I've got 150 million rows of data, zero budget, and might want to build a GUI for people to filter/aggregate/download slices. Help!"</p></li></ul><p><strong>Promoting events:</strong></p><ul><li><p>"JULY 8th: Whether you're deep into a new project, debugging a rogue script, or just curious what everyone's building these days, join us at Prefect in Foggy Bottom."</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i4GD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i4GD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 424w, https://substackcdn.com/image/fetch/$s_!i4GD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 848w, https://substackcdn.com/image/fetch/$s_!i4GD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 1272w, https://substackcdn.com/image/fetch/$s_!i4GD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i4GD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png" width="380" height="377.72" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:994,&quot;width&quot;:1000,&quot;resizeWidth&quot;:380,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i4GD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 424w, https://substackcdn.com/image/fetch/$s_!i4GD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 848w, https://substackcdn.com/image/fetch/$s_!i4GD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 1272w, https://substackcdn.com/image/fetch/$s_!i4GD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86013ca0-62de-4ac7-b614-4040cc8095f2_1000x994.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This is another super-clear post where the image and the text quickly tell you what it&#8217;s about</figcaption></figure></div><p>LinkedIn only shows the first couple of lines of your post, so you need those initial words plus your image<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> to communicate what your post is about immediately. That's what people who are new to LinkedIn often miss&#8212;they bury the point instead of leading with it.</p><h2><strong>Don't Worry About the Numbers</strong></h2><p>If you're not a "social media person," the idea of posting and getting feedback from strangers in the form of likes or comments (or no likes or comments!) might feel uncomfortable. But you can decide how much to care about the numbers&#8212;and you don't have to take them personally.</p><p>I once posted about using LLMs to help with Python syntax. It wasn't especially interesting. But it got 355,217 impressions and reached 196,366 people. I will probably never get that kind of engagement again&#8212;and that's fine.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xx8T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xx8T!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 424w, https://substackcdn.com/image/fetch/$s_!xx8T!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 848w, https://substackcdn.com/image/fetch/$s_!xx8T!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 1272w, https://substackcdn.com/image/fetch/$s_!xx8T!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xx8T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png" width="512" height="434.3937007874016" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:862,&quot;width&quot;:1016,&quot;resizeWidth&quot;:512,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xx8T!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 424w, https://substackcdn.com/image/fetch/$s_!xx8T!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 848w, https://substackcdn.com/image/fetch/$s_!xx8T!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 1272w, https://substackcdn.com/image/fetch/$s_!xx8T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F160f61c0-2ff4-4647-b54c-0e374acfe3ab_1016x862.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This was by far my most-viewed post, and I don&#8217;t even like it that much.</figcaption></figure></div><p>The way I think about this: be outcome-independent. Focus on clarity, not performance. I try to make the first lines clear, and I usually add an image, but I'm not optimizing for engagement. You can do more or less optimization, depending on your goals.</p><h2><strong>How to Get Started</strong></h2><p>If you're interested, here's how to start:</p><p><strong>Step 1: Fix the basics.</strong> Update your profile so it's accurate. Add a photo. Connect with former coworkers and other people you know.</p><p><strong>Step 2: Lurk.</strong> Follow people in your field who post things you care about. Notice what they&#8217;re doing.</p><p><strong>Step 3: Share</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a><strong>.</strong> Start posting when you have something to say. That might be asking for help with a tool, sharing an article you liked, or reposting a job from your organization with some context. Start small if you&#8217;re not sure how.</p><p><strong>What about connecting with strangers?</strong> Some people don't like it. I do it, and people do it with me all the time. I usually accept if we have a lot of mutual connections or if it&#8217;s clear to me why we might want to chat. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EHeh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EHeh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!EHeh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!EHeh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!EHeh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EHeh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png" width="390" height="260.0892857142857" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:390,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Generated image&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Generated image" title="Generated image" srcset="https://substackcdn.com/image/fetch/$s_!EHeh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!EHeh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!EHeh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!EHeh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33e3e305-ed01-4d92-9337-42d8d42d9a62_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">LinkedIn knows I don&#8217;t know these people</figcaption></figure></div><p>I spend a lot of time on LinkedIn because it helps with things I care about&#8212;events, side projects, my blog. So I post frequently, and I connect with people more than average. It's what I do instead of scrolling Reddit. If you don't have those goals, the time you spend will probably be less.</p><h2><strong>Why This Matters Now</strong></h2><p>If your job security assumptions have changed, or if you're in a field that's evolving faster than it used to, LinkedIn is now more valuable. For instance, for government folks&#8212;if you need to navigate the job market in ways you previously wouldn't have&#8212;this is a tool worth understanding.</p><p>Success isn't about becoming an influencer. It's about:</p><ul><li><p>Finding opportunities you'd otherwise miss</p></li><li><p>Being visible when it matters</p></li><li><p>Having an easy way to reach people&#8212;and be reached</p></li></ul><p>You don't need Premium. You don't need to post every day. You don't need thousands of connections. Just being present and clear about what you're doing, and reading what other people are doing, can be helpful.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://presentofcoding.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Present of Coding! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Images, not links. Put links in after the image or in the comments. You can't control how LinkedIn will render the link, and it's often not very good. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Depending on your organization and role, you may want to clear your posts with your manager&#8212;at least initially, to get a sense of what&#8217;s allowed.</p></div></div>]]></content:encoded></item></channel></rss>