I've just joined the Banley Internship Cohort 2026 (run by Kudagon) as a contributor. Wanted to share some thoughts on the technical shape of things - in particular, the architecture decisions made to get the foundational elements set up, as a contrast to "another crypto thing".
The problem, briefly
Retail crypto traders don't perform the math for their own strategy, namely assessing the required win rate, factoring in fees, and understanding the drawdown risk in case of consecutive losses. Meanwhile, the available options either massively oversimplify the math or require the end-user to have an account with them in order to do any calculations.
Banley is a calculator and risk education tool which does this math for you, with no backend, no account needed, and no information stored anywhere beyond your browser.
Why local-first?
Everything else stems from the design choice to not have a server or a user account system
Authentication is nonexistent, and anything that requires storage (risk profile, dashboard activity) is placed in the browser
This has implications on both privacy (nothing leaves the device) and the user journey - Objective O1 in the PRD (have a working strategy in under 2 minutes for 80% of users) could not possibly be met otherwise.
The counter to this decision is that the amount of data storable in the browser is limited to about half of the free space on the device, and that the user may delete or clear this data at any time. UI nudges and reminders about backups mitigate this issue, but it can't be entirely eliminated - and that's acceptable. One can't prevent the user from doing whatever they want to their device, so the response is to make the safe option the easy option.
PWAs over native apps
By using progressive web apps, you get cross-platform support with minimal development and no app store rejections. The cost of this decision is that the service workers need SSL in order to work offline, hence the domain needing a valid certificate.
On the feature development side, the PRD doesn't list items in the order one would normally implement them. Rather, it follows a logical order based on what components depend on what other components
Profile → Strategy Engine → Risk Education → Dashboard → Trade Logging → Education Library → Export/Sharing → Community → Settings → Advanced
A few examples of this can be seen in the implementation notes:
The dashboard's recent activity feed (4.2) depends on trade logging being implemented (4.1)
Contextual educational content (2.5) depends on both risk assessment (2.1) and the existence of the education library (5.1)
The image generation tools for sharing progress (7.2) depend on trade logging's progress tracking (4.2), not the strategy engine itself
If you were to implement in the order of the user's journey (make the dashboard available immediately, defer complex operations to later), you would have to continually delay features until later dates
By using the dependency list, you get to have everything ready to go when the user needs it.
Risk education is a first-class citizen
This ties back to the opening point - the risk education component is not just a fancy tooltip, but has its own section in the app and is listed as Layer 2 in the implementation plan, following right after the strategy engine and preceding the dashboard. The specific features include
required return percentage calculation based on user input
risk category (Low / Moderate / High / Aggressive)
loss simulation at 3rd, 5th, and 7th consecutive losses
recommendation for an alternative strategy if the initial one is found to be unreasonable
The PRD specifically calls out "risk assessment creates fear vs. education" as a named risk with its own mitigation: the need to balance discouragement and realism in the numbers without being outright threatening to the user.
Two strategy types, and that's it
The strategy engine only implements two types of strategies: Rollover (compounding) and Portfolio Growth. There are no others, and there won't be. The reason for this, per the PRD, is that those two encompass 90% of the use cases, and adding more would bloat the feature without sufficient value. It's a neat reminder that in software development, avoiding scope creep often requires just as much effort as implementing a feature.
My thoughts
Coming from a React / TS / Vite background, I'm particularly interested in
working with IndexedDB as a proper database, as opposed to localStorage.setItem(), namely the migrations and fallback strategies for browsers which don't support it
implementing the strategy engine's math for the fees, given the target exchanges (Binance, Bybit, Bitget) and the custom entry option
the export layer for generating Excel sheets with multiple tabs and data formatting, beyond just CSV export
If you're working on something similar and would like to discuss local-first development, PWA offline strategies, or IndexedDB specifics, feel free to comment!

Top comments (0)