Hey builders,
When you first start building on the Internet Computer Protocol (ICP), getting a basic "Hello World" canister running is pretty straightforward. The real headache starts when you try to scale that into a full-stack SaaS application with a multi-tool React frontend, user state tracking, and clean file handling.
While building VaultyPDF (a 15-tool on-chain PDF utility suite), I had to reorganize my project several times before finding a structure that didn't turn into spaghetti code. Here is the clean folder architecture I landed on for pairing React with Motoko.
1. Keep Backend Canisters Modular
Instead of stuffing thousands of lines of logic into a single main.mo file, separate your data types and helper functions early on:
src/
├── backend/
│ ├── main.mo # Main entry point & public actor methods
│ ├── types.mo # Custom user & document metadata types
│ └── storage.mo # Stable memory & state management helpers
Using a dedicated types.mo file makes it much easier to keep your Motoko records aligned with your frontend JavaScript/TypeScript interfaces.
2. Isolate Frontend Canister Calls
Never call your backend actor directly inside your UI components. Create a dedicated service or hook layer in your React folder so your UI stays focused purely on rendering:
src/
├── frontend/
│ ├── src/
│ │ ├── components/ # Reusable dark-mode UI cards & modals
│ │ ├── hooks/ # Custom hooks for auth & canister queries
│ │ ├── pages/ # Individual tool views (Merge, Split, Redact)
│ │ └── App.jsx # Main dashboard layout & routing
3. Handle Heavy Client-Side Processing Locally
On-chain storage and compute are great for user profiles, audit logs, and document metadata. However, for heavy PDF manipulation (like merging pages or applying visual redactions), run the heavy lifting directly in the user's browser via JavaScript, and only send the verified metadata or final state hashes to your Motoko canister. This keeps your cycle burn rate low and makes the UI feel instant.
Want to skip the boilerplate setup?
Setting up the React routing, dark-mode SaaS dashboard UI, and Motoko canister bindings from scratch easily eats up a couple of weeks.
If you want a ready-to-deploy foundation for your own ICP project, I packaged my entire 15-tool codebase into a clean starter template:
👉 Check out the VaultyPDF React + Motoko Boilerplate on Gumroad
How do you guys usually organize your Motoko projects when the codebase starts growing? Drop your folder tips below!
Top comments (0)