7 ms·
Show HN: TopHat Finance – free, open, and offline
- aniforprez 5y agoYou keep pseudo apologizing for this being "another" personal finance tracker. I'm actually not sure how many there are of note. I'm aware of YNAB and Toshl. Are there more that do similar things?
- wanderingmind 5y agohttps://www.firefly-iii.org/ https://www.firefly-iii.org/
- Krasnol 5y agoI use http://homebank.free.fr/ http://homebank.free.fr/ but I also don't need too many features.
- remote_only_eng 5y ago
- Athenodoros 5y agoHey HN - long time lurker etc. First off - I know, another personal finance app. However, I found none of the existing options matched what I wanted for myself: * Privacy-first - ideally a local app, and definitely no cloud storage of bank creds for automatic sync. I found this requires a polished statement upload flow, to save time on manual updates. * Good multi-currency support - this is bizarrely rare in the space. * Basic analytics and budgeting - ideally not as rigid as YNAB and friends, but at least something lightweight to tell me where my money is going and how that's changing. So over a few months during Covid, I put together TopHat for my own use: it's a SPA on GitHub Pages with no backend, where all data is stored in browser storage (plus a Dropbox sync option, which I wanted as a backup). It's a pretty standard stack (React, Redux, TS), and the code is all available on GitHub (https://github.com/Athenodoros/TopHat https://github.com/Athenodoros/TopHat) - don't judge too harshly, my day job isn't software engineering! That said, I've found it very rewarding to use something which I enjoy and which I've built - not to mention finally "finishing" a project... TopHat can load itself with some demo data, including an example bank statement for upload (check the notification on the top right). Hopefully this is interesting for folks - happy to answer any questions!
- deleted 5y ago[deleted]
- billylo 5y agoNice work! I made a similar tool, but focused on credit card spendings, runs on mobile, everything local, (with import from Canadian banks, also done locally using WebView so passwords never go elsewhere. I don't have enough time to continue to maintain it, but hope it can give you some other ideas to consider. Cheers. https://evergreen-labs.com/spendsimple/ https://evergreen-labs.com/spendsimple/
- andrew_ 5y ago"Desktop Required" I hate to doodie in the cereal, but... this is horrible UX. Warn the user, sure. But to block the user? I'm an Android user too; on tablets and phones. And both devices have landscape mode and a handy little checkbox in Brave/Chrome/etc that says "Desktop site." You had my interest. But you lost it immediately after visiting.
- Athenodoros 5y agoI definitely get the annoyance. The problem is, a mobile version of this is a very different thing, to the point that it's essentially a completely new app. Displaying a broken interface just to display something isn't helpful, even if I realise it makes it harder on the Show HN audience - I generally check HN on my phone too! For what it's worth, I'm not looking at user-agents or anything: it's cutting off at the point where the display starts looking awful. If you zoom out enough (plausible on a tablet, less so on a phone), then it will display as intended.
- throw0101a 5y ago> For what it's worth, I'm not looking at user-agents or anything: it's cutting off at the point where the display starts looking awful. I went to the site on my 27" iMac and got the 'Desktop Required' message. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.3 Safari/605.1.15 Resolution per Panopticlick [0] is 2560x1440x24. [0] https://panopticlick.eff.org/ https://panopticlick.eff.org/
- Athenodoros 5y agoIt's looking at the width, so that some fixed-width elements don't run into each other and wreck the display - if you expand the window a little it should work as expected. For what it's worth, I'm also running Firefox on MacOS, so I'd expect that to work given the right window size.
- InitialBP 5y agoIt's not just an annoyance, it makes your site literally unusable on a mobile device. What if I urgently need to access some details of my account and don't have laptop access. If I check "load desktop site" then load the site and let me deal with the broken UI. This is a ridiculous "feature" and the fact that you are defending something like this is a major turn off on ever using this product. What other hill would you be "willing to die on" for some seemingly miniscule yet exceptionally annoying feature.
- wnolens 5y agoCool, styling is slick. A good friend of mine has pretty much everything you built, but as an elaborate excel sheet (he's quite the wizard). I for one don't care to track individual transactions. I'm building something similar (more along the lines of your forecast page), and also opting to do without a backend server. Love the flow of no login and everything private. I've opted to use uPlot as I'm not using React, but "starred" Victory for consideration someday as it looks nice.
- idiocrat 5y agoCan you add an automatic consumption tax split? For example if I book an expense of 11,000 jpy, I need to split this into two accounts: - the expense account 10,000 jpy - the consumption tax amount 1,000 jpy Current tax rate is 10%, or 8% for selected items. The actual tax amount must be able to adjust by +/- 1 jpy to match the receipt amount, because of inconsistent rounding/truncation methods.
- simonmic 5y agoThat is lovely, one of the nicest UIs/set of reports I've seen so far. Congrats! We in the plain text accounting community should try to use it. (What's the license ?)
- Athenodoros 5y agoHonestly, I haven't really got as far as a license for the code yet - I don't know much about them, and people seem to have strong opinions about the standard options for OSS. I'd be interested in what folks recommend for something like this, and what the trade-offs are. Seems like MIT is the go-to in many cases? EDIT: Done, on GPLv3!
- simonmic 5y agoGPLv3+ gives you the most options. You can always relax it later if needed (easy to do as long as you are the sole copyright holder).
- alonchb 5y agoI also was in the same boat as you, I even paid for a year of YNAB. However, I had anxiety of giving full access to my bank account and importing it manually became a chore, soon I just stopped all together. I support your decision of blocking phone access, even tho it was a surprise, maybe explaining why is better than label it as a technical limitation Best of luck
- acemarke 5y agoLooks very nice! I see you're using Redux Toolkit and TypeScript, including some fairly heavy use of `createEntityAdapter`. Any feedback on using RTK? We're always interested in hearing how RTK is working for our users. A couple quick suggestions on the code itself: - I see a lot of custom hooks like `useAccountsPageState` [0], except that they're completely duplicating the `useSelector` signature. I think the right answer here is to start by defining the "pre-typed" `useAppSelector` hook we show in our TS usage docs [1]. Then, make sure your selectors have the correct `RootState` type. Finally, you can rewrite the hook as `const useAccountsPageState = () => useAppSelector(selectPageState)`. - It looks like you're importing `TopHatDispatch` into some other files. That has the risk of causing circular import problems, since it's importing from the store itself. You may want to rework functions like `updateSyncedCurrencies` [2] to be a thunk. (In fact, looking at the code, this looks like a very good candidate for RTK's `createAsyncThunk` API.) Also, it looks like this is going to end up dispatching a separate action for every item. It would probably be more efficient to fetch all the items first, then dispatch _one_ action with the combined fetched results. [0] https://github.com/Athenodoros/TopHat/blob/a916386edf/src/state/app/hooks.ts https://github.com/Athenodoros/TopHat/blob/a916386edf/src/st... [1] https://redux.js.org/tutorials/typescript-quick-start#define-typed-hooks https://redux.js.org/tutorials/typescript-quick-start#define... [2] https://github.com/Athenodoros/TopHat/blob/a916386edf/src/state/logic/currencies.ts#L70 https://github.com/Athenodoros/TopHat/blob/a916386edf/src/st...
- Athenodoros 5y agoI definitely have a lot of opinions about this :D. The main one is that RTK was fantastic (as are the docs!), and createEntityAdapter was definitely better than the equivalent that I wrote before finding it... A few more specific thoughts though: - createEntityAdapter was great, but one idea for an addition: I dislike having numbers as IDs (Will floating point precision bite me? Will I accidentally treat them as actual numbers? Do I need to cast them back for lookups or equality checks?), but I didn't get around to moving to strings, and preserving the sorting and ID generation with that in mind. Maybe RTK could bundle some utilities for managing this, like sorting functions and/or ascending ID generation to save others from my fate? I'll definitely start with these next time. - I really liked the Slice API in RTK, but I felt like I wanted to run nested slices quite a lot - breaking up serialisable state (ie. user data) and page state, but then breaking down further into individual data types or pages respectively, so that pages could "own" their own state (and maybe get as far as something like a managed Mixin for a page state, like the recurring transaction table). I spent some time writing a way to compose Slices, but I found that it made things probably more complicated than it needed to be - even if you end up with a load of useAccountsPageState-style duplication which is maintained manually. (I'll admit this was a while ago, so my memory of why I decided against this is a little rusty...). - I hadn't seen useAppDispatch and useAppSelector - I'll definitely swap over my copy of them in https://github.com/Athenodoros/TopHat/blob/main/src/state/shared/hooks.ts#L8 https://github.com/Athenodoros/TopHat/blob/main/src/state/sh... ... - I definitely got that the expected pattern is createAsyncThunk (or useDispatch more broadly) rather than my separate functions using TopHatDispatch. I spent some time tooling about with migrating over, but I felt like it was an additional abstraction layer that I didn't really need. I eventually went with a fairly strict flow of "Types -> Storage Logic -> Store Definition -> Actions -> Components" which dealt with the circular imports. I'd be interested in other thoughts behind the best practice though - maybe they're more obvious with other people, or a larger project?
- bradly 5y agoI’m not super familiar with offline apps, but does this mean if I clear my browser or switch browsers or switch computers all my data my be re-entered?
- Athenodoros 5y agoYes, that's correct - it's the price of the data not being synced elsewhere. That said, I was worried about that too, for myself: I've added in easy file import/export, and the option to sync to Dropbox (I'm using a separate account for TopHat syncing), so that people at least have options for backups.
- jeremywho 5y agoDoes this talk to an API to get the bank data or are you manually entering it?
- Athenodoros 5y agoNope, no APIs - instead, I've focussed on a smooth workflow for statement uploads and options for manual transaction reporting. I actually had a look around for APIs, and couldn't find anything that fitted with what I was trying to do: most services are specific to certain countries, and even with the various Open Banking initiatives around the world coverage is still limited and password storage upstream is often required (Plaid is obviously the standout here, although there are competitors and regional equivalents). That's expressly what I'm trying to avoid: ideally all of that could be managed locally in the browser, but until it can I'm not expecting to use it.
- Cynddl 5y agoIt doesn't appear to be very stable. I keep running into the following error on Firefox and need to empty the memory and cache, then restart everything again: > TopHat has hit an error, and has ended up in a bad state. You could go back to the home page, or check the developer tools for more information.
- Athenodoros 5y agoThat's interesting - I haven't seen errors in quite a while (on Firefox), and I've been using it myself for a few months. What are you doing just before it crashes?
- Cynddl 5y agoI believe it first happened after cleaning the demo to start from zero. But the apps is quite buggy in other ways. For instance, trying to add the GBP currency fails silently, but it's apparently due to using a free API? > "The *demo* API key is for demo purposes only. Please claim your free API key at (https://www.alphavantage.co/support/#api-key https://www.alphavantage.co/support/#api-key) to explore our full API offerings. It takes fewer than 20 seconds."
- Athenodoros 5y agoThat's right - without a backend server, I couldn't think of a great way to manage a private API key. That means that users have to sign up for their own keys (instructions on the "Currency Sync" page under "Settings") if they want to use currency sync. I thought I'd added a description to the error you get if you're still using the default "demo" key - clearly not, I'll add that it.
- infogulch 5y agoIt would be awesome if it was able to sync via git in a way that is compatible with plain text accounting: https://plaintextaccounting.org/ https://plaintextaccounting.org/ This would be a good way to for users to incrementally take more control over their financial infrastructure.
- regularperson25 5y agoHey, normal user here. It's not clear how can I change the default currency from AU to USD? I see the option, but just to create the currency, everything I enter and all other forecast etc, says "AU"
- Athenodoros 5y agoOops - I guess that needs to be better signposted... If you go to the currency page in the dialog (where you're creating USD), there's a "Default Currency" dropdown in the main section on the right. You might need to close out of any currency you're editing, but hopefully it's reasonably prominent once you do.