The Problem
Small businesses and freelancers need a desktop invoicing tool that can be customized without sending data to a cloud service. Existing options are either locked‑in to a single template or require a paid subscription, forcing users to compromise on branding or privacy.
What This Does
Manta is an Electron‑based desktop app that lets users design invoices with SVG logos, drag‑and‑drop line items, and export PDFs. The bulk of the UI lives under app/ (147 files, 129 code files) where app/App.jsx composes the main React tree and app/index.jsx boots the renderer process. Core actions such as creating contacts, invoices, and settings are defined in app/actions/*.jsx. UI widgets (e.g., app/components/form/Currency.jsx, app/components/form/Tax.jsx) render the flexible form, while app/constants/actions.jsx provides the action type constants used throughout the Redux flow.
Supporting projects include:
| Folder | Purpose | Code files |
|---|---|---|
preview/ | Live invoice preview rendering | 29 |
i18n/ | Translation data (81 JSON/YAML files) and helper i18n/i18n.js | 10 |
tour/ | Interactive onboarding walkthrough | 10 |
main/ | Electron main process entry (app.js) | 6 |
libs/, helpers/, modal/, __mocks__/ | Shared utilities, test mocks, small UI pieces | ≤6 each |
No single monolith; each folder can be built or run independently.
How It Is Wired
Execution starts in app.js, the Electron main script. It creates a browser window that loads app/index.html, which in turn runs the bundled renderer entry app/index.jsx. The webpack bundle (defined in webpack.config.js) pulls in:
- Renderer boot –
app/index.jsxrenders<App />fromapp/App.jsx. - Redux store –
app/reducers/index.jsxcombines reducers; actions are dispatched from UI components via the constants defined inapp/constants/actions.jsx. This constant file is the most‑connected hub (imported by 26 modules, no outgoing imports). - Form logic – UI components (
Currency.jsx,Tax.jsx, etc.) read/write Redux state and invoke helpers fromapp/helpers/. Duplicate UI blocks (e.g., currency handling) appear across multiple form components, inflating the blast radius. - Internationalisation – Components import
i18n/i18n.js, which loads language JSON files fromi18n/. This module has 16 inbound and 9 outbound edges, giving it a moderate instability score (0.36). - Preview generation – The
preview/code consumes the same Redux state to render a PDF‑ready preview, but its internal wiring is isolated from the main UI.
No circular dependencies were detected (210 modules, 357 import edges). The widest‑impact modules are the action constants and the higher‑order component _withFadeInAnimation.jsx (imported by 17 modules). Changing either will ripple through many parts of the UI.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/Manta.git
cd Manta
# Install dependencies (yarn lockfile present)
yarn install
# Build the renderer bundle
yarn webpack --config webpack.config.js # exact script name not defined; use webpack directly
# Start the Electron app
yarn electron . # or `npx electron .` if no script defined
Configuration: The app stores settings locally via electron-settings; no external environment variables are required. Translation files are loaded automatically from i18n/. If a custom template is needed, place the SVG/logo assets in static/ and reference them in the template JSON under app/components/....
If the repo lacks explicit npm scripts, the commands above follow the evidence from package.json, webpack.config.js, and the presence of Electron mock files.
Real‑World Use
A freelance graphic designer installs Manta on macOS, creates a client invoice using the “Minimal” template, drags the logo SVG into the header, and exports a PDF for email. The entire workflow runs locally; no network calls are made, preserving client confidentiality.
Code Health & Issues
- Medium – Enable Dependabot – Only one manifest (
package.json) is present; no.github/dependabot.yml. Without automated updates, security advisories stay unpatched. - High – Hub module volatility –
app/constants/actions.jsx(26 imports),i18n/i18n.js(16 imports, 9 outbound), and_withFadeInAnimation.jsx(17 imports) are central points. Frequent changes here cause wide‑impact rebuilds. - High – Duplicated code blocks – Repeated 6‑line snippets across
Currency.jsx,Tax.jsx,Discount.jsx, and several settings components. Consolidate into shared helpers. - Medium – Deep nesting –
app/components/invoices/Invoice.jsxreaches six indentation levels, making logic hard to follow; refactor with early returns. - Medium – Oversized test file –
app/helpers/__tests__/form.spec.jsspans 754 lines; split into focused test suites. - Low – Stale TODO/FIXME – Three markers in
test/spec.js; create corresponding issue tickets or resolve them.
No critical or high‑severity security findings were reported. CI is configured via Travis (.travis.yml), and a license file (LICENSE) is present.
The Bottom Line
Manta delivers a fully local, customizable invoicing UI built on React/Electron, with a clear separation of preview, i18n, and core app code. The codebase is functional but suffers from duplicated UI logic and a few large, tightly coupled modules that increase change risk. It is suitable for teams comfortable with JavaScript/React who need a privacy‑first invoicing tool and are prepared to address the identified maintainability concerns.