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:

FolderPurposeCode files
preview/Live invoice preview rendering29
i18n/Translation data (81 JSON/YAML files) and helper i18n/i18n.js10
tour/Interactive onboarding walkthrough10
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:

  1. Renderer boot – app/index.jsx renders <App /> from app/App.jsx.
  2. Redux store – app/reducers/index.jsx combines reducers; actions are dispatched from UI components via the constants defined in app/constants/actions.jsx. This constant file is the most‑connected hub (imported by 26 modules, no outgoing imports).
  3. Form logic – UI components (Currency.jsx, Tax.jsx, etc.) read/write Redux state and invoke helpers from app/helpers/. Duplicate UI blocks (e.g., currency handling) appear across multiple form components, inflating the blast radius.
  4. Internationalisation – Components import i18n/i18n.js, which loads language JSON files from i18n/. This module has 16 inbound and 9 outbound edges, giving it a moderate instability score (0.36).
  5. 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.jsx reaches six indentation levels, making logic hard to follow; refactor with early returns.
  • Medium – Oversized test file – app/helpers/__tests__/form.spec.js spans 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.