<?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: Sheaf</title>
    <description>The latest articles on DEV Community by Sheaf (@sheaf).</description>
    <link>https://dev.to/sheaf</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%2F4187690%2F657c1177-f193-4842-94ed-e5ac31d2e9aa.png</url>
      <title>DEV Community: Sheaf</title>
      <link>https://dev.to/sheaf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sheaf"/>
    <language>en</language>
    <item>
      <title>Your Harvest bill went up. Here is how to work out next year before it lands.</title>
      <dc:creator>Sheaf</dc:creator>
      <pubDate>Sun, 18 Oct 2026 09:08:49 +0000</pubDate>
      <link>https://dev.to/sheaf/your-harvest-bill-went-up-here-is-how-to-work-out-next-year-before-it-lands-2jdb</link>
      <guid>https://dev.to/sheaf/your-harvest-bill-went-up-here-is-how-to-work-out-next-year-before-it-lands-2jdb</guid>
      <description>&lt;p&gt;If you run a small agency on Harvest, there's a decent chance your last renewal email made you sit up. The question all over forums this year is the same one: "why did my bill go up so much, and what will next year look like?"&lt;/p&gt;

&lt;p&gt;Here's the short version, and a quick way to work out your own number before the renewal lands.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;p&gt;Harvest still charges per seat. The seat price actually went down a little. Teams is $9 a seat per month on yearly billing, $11 monthly.&lt;/p&gt;

&lt;p&gt;The new part is usage. On what Harvest calls Flex billing, you also pay for active projects, active clients, active tasks and invoicing, based on the previous billing period. Only things with time tracked in that period count. Each plan includes some usage for free, but Harvest doesn't publish the allowance or the per-item rates.&lt;/p&gt;

&lt;p&gt;There's also Unlimited billing, which swaps the usage charges for one fixed fee. That fee isn't published either.&lt;/p&gt;

&lt;p&gt;Harvest's own help article explains why the first bill can look fine and the second one doesn't. For new accounts, usage starts at the second paid renewal. Their example is a bill going "from a seats-only $44 to $404".&lt;/p&gt;

&lt;h2&gt;
  
  
  Who gets hit hardest
&lt;/h2&gt;

&lt;p&gt;It's less about team size and more about how you split your work. You're most exposed if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;have lots of small clients instead of a few big ones&lt;/li&gt;
&lt;li&gt;open a new project per job, sprint or month&lt;/li&gt;
&lt;li&gt;use many tasks to categorize time&lt;/li&gt;
&lt;li&gt;send a lot of invoices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A five-person studio with 30 active clients can pay more than a much bigger team with five large accounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work out your number in 10 minutes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Find your renewal date and whether you're billed yearly or monthly.&lt;/li&gt;
&lt;li&gt;Run a report for your last billing period. Count the projects, clients and tasks that had any time tracked, and how many invoices you sent.&lt;/li&gt;
&lt;li&gt;Ask Harvest support for a written quote for both Flex and Unlimited, using those counts. Ask if you're on a legacy plan, too.&lt;/li&gt;
&lt;li&gt;Export your data now, whatever you decide. It's much easier while you still have full access.&lt;/li&gt;
&lt;li&gt;Don't sign another year until you know what the year costs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Staying is fine
&lt;/h2&gt;

&lt;p&gt;If the quote works for you, stay. Harvest is a mature product with good apps and integrations, and some people got a lower price for paying upfront. Switching takes time and that has a cost.&lt;/p&gt;

&lt;p&gt;If it doesn't work, there are flat-priced options now. Toggl Track, Clockify and Keito are the usual ones. Disclosure, we make one too: Sheaf, which imports your whole Harvest account in one go, including old invoices so nothing gets billed twice. It's free while we're in beta.&lt;/p&gt;

&lt;p&gt;We keep a longer write-up with sources and the reported numbers here: &lt;a href="https://sheaf.guestleaf.app/guides/harvest-pricing-2026" rel="noopener noreferrer"&gt;Harvest's 2026 price increase, explained&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you've already been through a renewal, what did yours do? Curious how wide the range is.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>freelance</category>
      <category>business</category>
      <category>saas</category>
    </item>
    <item>
      <title>I almost added a PDF library. A print stylesheet was enough.</title>
      <dc:creator>Sheaf</dc:creator>
      <pubDate>Sat, 17 Oct 2026 07:52:32 +0000</pubDate>
      <link>https://dev.to/sheaf/i-almost-added-a-pdf-library-a-print-stylesheet-was-enough-5eha</link>
      <guid>https://dev.to/sheaf/i-almost-added-a-pdf-library-a-print-stylesheet-was-enough-5eha</guid>
      <description>&lt;p&gt;I was about to add a PDF library to our project. Then I remembered every browser already has one.&lt;/p&gt;

&lt;p&gt;Here's the situation. We make &lt;a href="https://sheaf.guestleaf.app" rel="noopener noreferrer"&gt;Sheaf&lt;/a&gt;, a time tracking and invoicing app. After a week with basically no visitors, we decided to build a few small free tools that people actually search for. The first one was an invoice generator: fill in a form, get a PDF, no account.&lt;/p&gt;

&lt;p&gt;My first plan was the usual one. Send the form to the server, render a PDF there, send the file back.&lt;/p&gt;

&lt;p&gt;Then I started listing what that meant. A PDF library. Fonts. A server route. Rate limits, because now anyone can make our server do work. And people's client names, addresses and amounts flowing through our backend, for a free tool.&lt;/p&gt;

&lt;p&gt;That's a lot of stuff for a page that's supposed to be simple.&lt;/p&gt;

&lt;p&gt;So I tried the lazy option instead: &lt;code&gt;window.print()&lt;/code&gt; and a print stylesheet.&lt;/p&gt;

&lt;p&gt;The preview on the page is already a nice looking invoice, built from normal HTML. When you print, I hide everything except that preview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14mm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.buttons&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.invoice&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The person clicks Download PDF, the print window opens, they pick "Save as PDF", done. The browser does the font rendering, the page breaks and the file. On phones it goes through the share sheet.&lt;/p&gt;

&lt;p&gt;A few things I didn't expect:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nothing to store means nothing to worry about.&lt;/strong&gt; The form saves to localStorage so your details are there next time. Nothing leaves the browser, so there's no privacy policy paragraph to write and no data to protect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's an easy promise to keep.&lt;/strong&gt; The page says "Your invoice stays in this browser", and it's true by design, not because of a policy. A lot of free invoice tools ask for your email first. This one can't, because there's nowhere to send it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It made the next tools easy.&lt;/strong&gt; The time card calculator and the hourly rate calculator use the same idea: plain HTML, a bit of JavaScript, localStorage, print CSS. Each one took an afternoon.&lt;/p&gt;

&lt;p&gt;The one downside: you can't control the browser's own header and footer (the date and URL in the margins). Most browsers have a checkbox to turn them off, and that's fine for an invoice.&lt;/p&gt;

&lt;p&gt;If you're about to add a PDF library, try a print stylesheet first. It might be all you need.&lt;/p&gt;

&lt;p&gt;Here's the generator if you want to see it working: &lt;a href="https://sheaf.guestleaf.app/tools/invoice-generator" rel="noopener noreferrer"&gt;free invoice generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's something you almost overbuilt before finding the simple version?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My import worked on clean data. Messy data broke it six ways.</title>
      <dc:creator>Sheaf</dc:creator>
      <pubDate>Fri, 16 Oct 2026 02:15:38 +0000</pubDate>
      <link>https://dev.to/sheaf/my-import-worked-on-clean-data-messy-data-broke-it-six-ways-1cfg</link>
      <guid>https://dev.to/sheaf/my-import-worked-on-clean-data-messy-data-broke-it-six-ways-1cfg</guid>
      <description>&lt;p&gt;The first version of our Harvest import worked great.&lt;/p&gt;

&lt;p&gt;On my test account. Which had three clients, two projects, and nothing weird in it at all.&lt;/p&gt;

&lt;p&gt;Some context. I'm building &lt;a href="https://sheaf.guestleaf.app" rel="noopener noreferrer"&gt;Sheaf&lt;/a&gt;, a time tracking and invoicing app for small agencies. A lot of the people trying it are leaving Harvest after its price change, and the first thing they ask is whether they can bring their history with them. So the import matters more than almost anything else in the app. If it gets someone's invoices wrong, they're gone.&lt;/p&gt;

&lt;p&gt;Real accounts aren't three clients and two projects. They're years of stuff. Old clients, deleted projects, invoices in four currencies, notes someone pasted a whole email into.&lt;/p&gt;

&lt;p&gt;So before letting anyone near it, I made a fake account that looked like it had been used for years. Messy on purpose. Then I ran the import again.&lt;/p&gt;

&lt;p&gt;It broke in six different ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Canadian invoice was off by a cent.&lt;/strong&gt; Quebec sales tax is 9.975%. I was storing tax rates with two decimals. A cent sounds like nothing until it's on an invoice someone's accountant is checking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Invoice numbers stopped making sense.&lt;/strong&gt; Most accounts number invoices 1001, 1002, 1003. One of mine used INV-0099. After importing it, Sheaf had no idea what the next number should be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A long note got chopped.&lt;/strong&gt; Someone had pasted almost 6,000 characters into a time entry note. My limit was lower than that, so the end just vanished. Nobody would have noticed until they needed it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mileage lost its miles.&lt;/strong&gt; An expense for 120 miles came across as just an amount. The miles were gone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One permission error killed everything.&lt;/strong&gt; If the person importing isn't an admin, Harvest won't show them invoices. My import treated that as a fatal error and stopped. Now it brings over everything they can see and tells them what's missing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importing twice undid people's work.&lt;/strong&gt; This one scared me the most. People don't switch tools in a day. They import, try it for a week, and import again to catch up. My second run was quietly overwriting things they had already fixed in Sheaf. Now it only adds what's new and leaves their changes alone.&lt;/p&gt;

&lt;p&gt;None of these would have shown up with clean test data. Every one of them would have shown up with a real customer, probably in their first week, which is the worst possible time.&lt;/p&gt;

&lt;p&gt;So that's my lesson, and it's not a new one: your test data is too clean. Make a version that looks like five years of real, careless use, and run everything against that.&lt;/p&gt;

&lt;p&gt;And if you're leaving Harvest yourself, &lt;a href="https://sheaf.guestleaf.app" rel="noopener noreferrer"&gt;Sheaf&lt;/a&gt; is free while it's in beta. The import takes a couple of minutes, and now it handles the messy stuff too.&lt;/p&gt;

&lt;p&gt;What's the weirdest thing you've found in a customer's real data?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>startup</category>
      <category>testing</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
