<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lawrence Locke</title>
    <description>The latest articles on DEV Community by Lawrence Locke (@lawrencelocke).</description>
    <link>https://dev.to/lawrencelocke</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2296988%2Fcf75da17-5749-4da1-8f79-b21b9f83e894.png</url>
      <title>DEV Community: Lawrence Locke</title>
      <link>https://dev.to/lawrencelocke</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lawrencelocke"/>
    <language>en</language>
    <item>
      <title>Turning messy Airbnb / Vrbo / Booking.com payout CSVs into per-property profit</title>
      <dc:creator>Lawrence Locke</dc:creator>
      <pubDate>Sun, 21 Jun 2026 14:36:42 +0000</pubDate>
      <link>https://dev.to/hostpayout/turning-messy-airbnb-vrbo-bookingcom-payout-csvs-into-per-property-profit-3j97</link>
      <guid>https://dev.to/hostpayout/turning-messy-airbnb-vrbo-bookingcom-payout-csvs-into-per-property-profit-3j97</guid>
      <description>&lt;p&gt;Hosts rarely have a single clean ledger. Revenue comes from one export, platform fees from another, and operating costs from a bank or card CSV. Each source uses different columns, currencies, fee structures, and date formats. &lt;a href="https://hostpayout.com" rel="noopener noreferrer"&gt;HostPayout&lt;/a&gt; turns that pile into one per-property profit view. Here's the shape of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four exports, four formats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Airbnb&lt;/strong&gt; — payout CSVs: gross, host fee, taxes, adjustments, payout date&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vrbo&lt;/strong&gt; — owner statements with their own column names&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Booking.com&lt;/strong&gt; — finance exports with commission and payout columns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bank / card&lt;/strong&gt; — free-form expense rows with no notion of "property"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of them agree on headers, sign conventions (is a fee a negative number or a separate column?), currency, or how dates are written.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: normalize into one transaction model
&lt;/h2&gt;

&lt;p&gt;Every row, from every file, maps onto the same record:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;date&lt;/code&gt; — parsed to a real date regardless of source format&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;property&lt;/code&gt; — which unit it belongs to&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt; — income, platform fee, tax/adjustment, or expense&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;amount&lt;/code&gt; + &lt;code&gt;currency&lt;/code&gt; — kept in the original currency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Getting sign conventions and currency right here is most of the battle: a "fee" is a negative amount in one export and a positive value in a separate column in another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: assign to properties — and keep it editable
&lt;/h2&gt;

&lt;p&gt;A bank CSV doesn't know which apartment a cleaning charge belongs to, so import isn't the end — it's a &lt;strong&gt;review&lt;/strong&gt; step. You assign properties, fix anything miscategorized, and delete what doesn't belong &lt;strong&gt;before&lt;/strong&gt; the numbers hit your reports. Rows stay editable afterward, so a mistake is a quick fix, not a locked-in error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: roll up to monthly net profit per property
&lt;/h2&gt;

&lt;p&gt;Once everything is normalized and assigned, the report is the easy part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Income, platform fees, and expenses per property&lt;/li&gt;
&lt;li&gt;Net profit per property, per month&lt;/li&gt;
&lt;li&gt;A portfolio summary across all units&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No workbook, no formulas to maintain — the same three-step loop every month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just connect the APIs?
&lt;/h2&gt;

&lt;p&gt;Because CSV exports work in any country and currency, need no bank login or Plaid, and don't break when a platform changes its API. You upload a file you already have, review it, and see whether each property actually made money.&lt;/p&gt;

&lt;p&gt;Try it with your own export: &lt;strong&gt;&lt;a href="https://hostpayout.com" rel="noopener noreferrer"&gt;hostpayout.com&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try HostPayout:&lt;/strong&gt; &lt;a href="https://hostpayout.com/short-term-rental-owner-statement-csv" rel="noopener noreferrer"&gt;Owner statement CSV tracking&lt;/a&gt; · &lt;a href="https://hostpayout.com/airbnb-profit-tracker" rel="noopener noreferrer"&gt;Airbnb profit tracker&lt;/a&gt; · &lt;a href="https://hostpayout.com/booking-com-profit-tracker" rel="noopener noreferrer"&gt;Booking.com profit tracker&lt;/a&gt; · &lt;a href="https://hostpayout.com/signup" rel="noopener noreferrer"&gt;Upload your CSV free&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>programming</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Why I built a CSV-first rental profit tracker — no Plaid, no bank login</title>
      <dc:creator>Lawrence Locke</dc:creator>
      <pubDate>Sun, 21 Jun 2026 14:35:15 +0000</pubDate>
      <link>https://dev.to/hostpayout/why-i-built-a-csv-first-rental-profit-tracker-no-plaid-no-bank-login-3eo6</link>
      <guid>https://dev.to/hostpayout/why-i-built-a-csv-first-rental-profit-tracker-no-plaid-no-bank-login-3eo6</guid>
      <description>&lt;p&gt;Most short-term-rental finance tools start the same way: connect your bank through Plaid, link your Airbnb account, grant a pile of OAuth scopes. If you're a host outside the US, or you just don't want to hand bank credentials to another SaaS, that's where the tool ends for you.&lt;/p&gt;

&lt;p&gt;I wanted to see whether each property I run was actually making money — without any of that. So I built &lt;a href="https://hostpayout.com" rel="noopener noreferrer"&gt;HostPayout&lt;/a&gt; to be &lt;strong&gt;CSV-first&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start from the export you already have
&lt;/h2&gt;

&lt;p&gt;Every platform already lets you download your numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Airbnb&lt;/strong&gt; — payout CSVs with host fees, taxes, and adjustments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vrbo / Booking.com&lt;/strong&gt; — owner statements and finance exports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your bank or card&lt;/strong&gt; — expense CSVs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You export the file, drag it in, and HostPayout does the rest. No account linking, no Plaid, no bank login.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why CSV beats integrations (for this problem)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Works in any country and currency&lt;/strong&gt; — not just US banks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No credentials shared&lt;/strong&gt; — you only ever upload a file you already have&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing is locked&lt;/strong&gt; — rows stay editable and deletable, so you can fix a miscategorized expense instead of living with it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resilient&lt;/strong&gt; — there's no integration to break when a platform changes its API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Upload your CSV&lt;/strong&gt; from a rental platform or your bank&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review transactions&lt;/strong&gt; — assign properties, clean up expenses, fix anything unclear before saving&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;See real profit&lt;/strong&gt; — income, expenses, and net profit by property, updated every month&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the whole loop, and it's the same on every plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free forever for the first 5 properties
&lt;/h2&gt;

&lt;p&gt;The core import → review → report workflow is free for up to 5 properties, no credit card. If you outgrow that, paid tiers add more property room — and if paid access ever lapses, your existing data and reporting stay available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who it's for
&lt;/h2&gt;

&lt;p&gt;Hosts and small operators who get revenue in one export, fees in another, and costs from a bank CSV — and just want one monthly view of whether each property is making money, without rebuilding a spreadsheet every month.&lt;/p&gt;

&lt;p&gt;Try it with the export you already have: &lt;strong&gt;&lt;a href="https://hostpayout.com" rel="noopener noreferrer"&gt;hostpayout.com&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try HostPayout:&lt;/strong&gt; &lt;a href="https://hostpayout.com/airbnb-profit-tracker" rel="noopener noreferrer"&gt;Airbnb profit tracker&lt;/a&gt; · &lt;a href="https://hostpayout.com/vrbo-expense-tracking" rel="noopener noreferrer"&gt;Vrbo expense tracking&lt;/a&gt; · &lt;a href="https://hostpayout.com/booking-com-profit-tracker" rel="noopener noreferrer"&gt;Booking.com profit tracker&lt;/a&gt; · &lt;a href="https://hostpayout.com/demo" rel="noopener noreferrer"&gt;Try the CSV demo (no signup)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>startup</category>
      <category>webdev</category>
      <category>saas</category>
    </item>
    <item>
      <title>Building a self-updating .ics auction calendar from 150+ sources</title>
      <dc:creator>Lawrence Locke</dc:creator>
      <pubDate>Sun, 21 Jun 2026 14:33:26 +0000</pubDate>
      <link>https://dev.to/hammeralert/building-a-self-updating-ics-auction-calendar-from-150-sources-1bpe</link>
      <guid>https://dev.to/hammeralert/building-a-self-updating-ics-auction-calendar-from-150-sources-1bpe</guid>
      <description>&lt;p&gt;&lt;a href="https://hammeralert.com" rel="noopener noreferrer"&gt;HammerAlert&lt;/a&gt; tracks upcoming auctions from 150+ houses and exposes them as a single calendar feed you can subscribe to in Apple Calendar, Google Calendar, or Outlook. Here's how the calendar side of it actually works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hard part isn't the calendar — it's the sources
&lt;/h2&gt;

&lt;p&gt;Every auction house publishes its schedule differently: different page structures, date formats, time zones, category names, and languages. Before anything can land in a calendar, all of it has to be pulled in and normalized into one shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  One schema for every sale
&lt;/h2&gt;

&lt;p&gt;Each upcoming sale becomes a record with the same fields, no matter where it came from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;house&lt;/code&gt; — Christie's, Phillips, Bukowskis…&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt; — the sale name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;category&lt;/code&gt; — jewellery, watches, modern &amp;amp; contemporary art…&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;region&lt;/code&gt; — UK, Europe, US, Asia &amp;amp; Pacific&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start&lt;/code&gt; — start date/time, stored in UTC&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;url&lt;/code&gt; — link back to the house's own listing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normalizing region, category, and time zone up front is what makes filtering and a clean calendar possible later.&lt;/p&gt;

&lt;h2&gt;
  
  
  A personal, tokenized .ics feed
&lt;/h2&gt;

&lt;p&gt;Calendar apps don't authenticate against an API — they fetch a plain &lt;code&gt;.ics&lt;/code&gt; URL on a schedule. So every signed-in user gets their own tokenized feed:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hammeralert.com/api/calendar/your-personal-token.ics&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The token identifies the user and their preferences without a login, so the URL is safe to paste into a calendar app but still personal. The endpoint renders the filtered set of sales as standard iCalendar &lt;code&gt;VEVENT&lt;/code&gt;s on each request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering happens server-side
&lt;/h2&gt;

&lt;p&gt;Because the feed is generated per token, the user's saved preferences — categories, regions, specific houses — are applied when the &lt;code&gt;.ics&lt;/code&gt; is built. The calendar app only ever sees the sales that matter to that person, not all 2,000+ upcoming lots.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staying fresh automatically
&lt;/h2&gt;

&lt;p&gt;Calendar clients re-fetch the feed periodically. When a house adds, moves, or cancels a sale, the next fetch reflects it — no re-importing, no manual sync. Add the URL once and it keeps itself up to date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Normalize messy sources into one schema &lt;em&gt;before&lt;/em&gt; you think about output&lt;/li&gt;
&lt;li&gt;A tokenized &lt;code&gt;.ics&lt;/code&gt; URL gives you personalization without an auth flow in the calendar client&lt;/li&gt;
&lt;li&gt;Let the calendar app's own refresh cycle do your syncing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see it in action at &lt;strong&gt;&lt;a href="https://hammeralert.com" rel="noopener noreferrer"&gt;hammeralert.com&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;More from HammerAlert:&lt;/strong&gt; &lt;a href="https://hammeralert.com/auctions" rel="noopener noreferrer"&gt;Browse 2,000+ upcoming auctions&lt;/a&gt; · &lt;a href="https://hammeralert.com/guide/how-to-track-auction-calendars" rel="noopener noreferrer"&gt;How to track auction calendars&lt;/a&gt; · &lt;a href="https://hammeralert.com/auctions/house/sothebys" rel="noopener noreferrer"&gt;Sotheby's auction calendar&lt;/a&gt; · &lt;a href="https://hammeralert.com/auction-market-calendar-index" rel="noopener noreferrer"&gt;Auction market calendar index&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>programming</category>
      <category>api</category>
    </item>
    <item>
      <title>How I track upcoming auctions across 150+ houses in one calendar feed</title>
      <dc:creator>Lawrence Locke</dc:creator>
      <pubDate>Sun, 21 Jun 2026 14:32:08 +0000</pubDate>
      <link>https://dev.to/hammeralert/how-i-track-upcoming-auctions-across-150-houses-in-one-calendar-feed-3el</link>
      <guid>https://dev.to/hammeralert/how-i-track-upcoming-auctions-across-150-houses-in-one-calendar-feed-3el</guid>
      <description>&lt;p&gt;Anyone who follows art, watch, jewellery or design auctions runs into the same problem: the sales are spread across a hundred different auction-house websites. Christie's, Sotheby's, Phillips, Bonhams, Bukowskis, Dorotheum — each publishes its own schedule, in its own layout, on its own page. There's no shared calendar, so it's easy to find out about a sale the day after it closed.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://hammeralert.com" rel="noopener noreferrer"&gt;HammerAlert&lt;/a&gt; to fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  One place for every house
&lt;/h2&gt;

&lt;p&gt;HammerAlert tracks upcoming auctions across &lt;strong&gt;150+ houses worldwide&lt;/strong&gt; and lets you browse them by category, region, or house — no account needed. Thousands of upcoming sales sit in one consistent view instead of a hundred different ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set your preferences once
&lt;/h2&gt;

&lt;p&gt;When you sign in, you choose what you actually care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Categories&lt;/strong&gt; — jewellery, watches, modern &amp;amp; contemporary art, prints, design…&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regions&lt;/strong&gt; — UK, Europe, US, Asia &amp;amp; Pacific&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specific houses&lt;/strong&gt; — follow only the ones you buy from&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else gets filtered out, so you're not drowning in sales you'll never bid on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep it in your own calendar
&lt;/h2&gt;

&lt;p&gt;This is the part I use most. Instead of another dashboard to remember to check, HammerAlert gives you a personal calendar feed:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hammeralert.com/api/calendar/your-personal-token.ics&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add that URL once to Apple Calendar, Google Calendar, or Outlook and your upcoming auctions show up next to everything else. When the schedule changes, the calendar updates on its own — no re-importing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alerts when timing matters
&lt;/h2&gt;

&lt;p&gt;On top of the calendar there's a &lt;strong&gt;weekly email digest&lt;/strong&gt; and &lt;strong&gt;per-auction alerts&lt;/strong&gt; for the sales you don't want to miss as they get close.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why one calendar beats a hundred tabs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No more checking individual house websites&lt;/li&gt;
&lt;li&gt;One filtered view of the whole market&lt;/li&gt;
&lt;li&gt;Auctions live in the calendar you already use&lt;/li&gt;
&lt;li&gt;Updates follow automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you track auctions for work or for a collection, browse the index first and build your own calendar here: &lt;strong&gt;&lt;a href="https://hammeralert.com" rel="noopener noreferrer"&gt;hammeralert.com&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;More from HammerAlert:&lt;/strong&gt; &lt;a href="https://hammeralert.com/auctions" rel="noopener noreferrer"&gt;Browse upcoming auctions&lt;/a&gt; · &lt;a href="https://hammeralert.com/auctions/house/christies" rel="noopener noreferrer"&gt;Christie's auction calendar&lt;/a&gt; · &lt;a href="https://hammeralert.com/guide/jewellery-auction-calendar" rel="noopener noreferrer"&gt;Jewellery auction calendar guide&lt;/a&gt; · &lt;a href="https://hammeralert.com/guide/watch-auction-calendar" rel="noopener noreferrer"&gt;Watch auction calendar guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>api</category>
    </item>
  </channel>
</rss>
