# Marumie publishes political funding data from a public dashboard and an admin console

> Marumie is an open source dashboard for political funding transparency, built by the Team Mirai engineering team with Next.js, Prisma and Supabase. It ships two separate frontends, a public one for visualisation and an admin one for data import and report export, and it deploys through a manual workflow that only tags a release when both succeed.

**team-mirai/marumie** — 政治資金の流れを透明性を持って公開するプラットフォームです

- Repository: https://github.com/team-mirai/marumie
- Website: https://marumie.team-mir.ai
- Stars: 703 · Forks: 81
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/team-mirai-marumie

## Two frontends, because publishing and administering are different jobs

Marumie is a web application whose stated purpose is to make the flow of political funding understandable, letting politicians and political organisations publish their accounting data transparently so that citizens can follow where the money comes from and where it goes. Data is imported from cloud accounting services such as MF Cloud and freee, and the project also supports producing the political funding report itself.

The codebase is split into two applications. The webapp/ directory is the public facing frontend for visualisation, and the admin/ directory is the management console for entering and managing data. A third top level directory, shared/, holds the models, type definitions and utility functions that both applications use, so the two sides agree on the shape of the data without duplicating it.

That split is the first design decision worth understanding, and it is more than a naming convention. An admin surface that imports files and exports regulatory XML has different security needs, different deployment considerations and a different audience from a page a member of the public reads. Keeping them as separate applications with separate package.json files means a deployment can fail on one side without exposing the other.

The project is developed by the Team Mirai Nagatacho engineering team, and it is hosted at marumie.team-mir.ai.

## Bounded contexts name the business areas in the directory tree

Inside both applications, the server code is organised as bounded contexts rather than by technical layer, and the directory names state what each one does.

The public application has a context directory called public-finance, which the tree describes as the publication and visualisation of political funding data. The admin application carries four: auth for authentication, data-import for pulling in transaction data, report for exporting the political funding report as XML, and shared for code that crosses context boundaries. Both applications also have app/ for the Next.js App Router, client/ for client side components, types/ for type definitions, and tests/.

The report context is the one that reveals the shape of the domain. Exporting the political funding report as XML means the project is not free to invent a data model. It has to accept what the accounting system produced, keep the fund balances and the transaction ledger consistent, and emit a document in the format the filing process expects. A team reusing this code for a different jurisdiction inherits that constraint.

The webapp/ tree also lists a types/ directory and a tests/ directory, so type definitions are kept explicitly rather than inferred, and the admin tree has a middleware.ts at its level, which is where cross-request concerns such as authentication would sit in a Next.js application.

## A conventional modern stack: Next.js 16, React 19, Prisma, Supabase

The technical stack is listed in full, and every part of it is a current mainstream choice rather than something unusual. The frontend is Next.js 16 with React 19 and TypeScript. The backend is Prisma ORM on top of Supabase, which means the database is PostgreSQL reached through Supabase. Styling is Tailwind CSS v4.

For charts the project names three libraries rather than one, Recharts, ApexCharts and Nivo, which suggests different visualisation needs are served by different tools, or that the choice was made incrementally. The database is PostgreSQL via Supabase, and development uses pnpm and Biome. Tests run on Jest.

The repository root shows the tooling around the applications. There is a knip.json for detecting unused files and exports, a renovate.json for dependency update automation, a .dependency-cruiser.cjs file for architectural rules, a .coderabbit.yml configuration, CODEOWNERS, SECURITY.md, CLAUDE.md, a .mcp.json file and a .claude/ directory, and a pre-commit style setup is not listed but the presence of biome.json and the format script shows where formatting is enforced.

Two of these are worth calling out. The dependency cruiser configuration is run as separate scripts for admin and webapp, which means the import boundaries between the bounded contexts are a check that fails the build rather than a convention in a document. The check:usecase-shape script, run with the node test runner, appears to enforce a shape on use cases across the two applications.

## Local development boots Supabase and both apps at once

The root package.json is a pnpm workspace with packages/*, admin and webapp, and it declares pnpm 10.34.6 as the package manager. The development scripts are the quickest way to understand the intended workflow.

```json
  "dev": "pnpm supabase:start && concurrently \"pnpm dev:webapp\" \"pnpm dev:admin\"",
  "dev:setup": "pnpm install && pnpm db:reset && echo 'Setup complete! Run: pnpm dev'",
  "dev:webapp": "pnpm --filter webapp dev",
  "dev:admin": "pnpm --filter admin dev",
```

The setup script installs, resets the database and prints a hint to run the dev script. The dev script starts the local Supabase instance first and only then launches both frontends together, which is the right order, since the applications need a database and a Supabase service to talk to.

The environment template shows the local addresses. The database connection string points at port 54332 on the loopback address, which is the port a local Supabase stack exposes for Postgres, and a separate direct URL is provided for the same database.

```bash
DATABASE_URL="postgresql://postgres:postgres@127.0.0.1:54332/postgres"
DIRECT_URL="postgresql://postgres:postgres@127.0.0.1:54332/postgres"
```

The seeding story is handled for you. The comment in the environment template explains that the seed command reads the Supabase URL and the service role key from the running local instance automatically, so those variables only need setting when seeding a Supabase project that is not the local one. The supabase/ directory holds the local environment configuration and templates, and the prisma/ directory holds the schema, the migration files and the seed data.

## Production deploys are manual, and the release tag is a receipt

The deployment story is the most carefully documented part of the project, and it explains why the release tag is worth reading as a record rather than as a version number.

Production deployment is done by running the Deploy Production GitHub Actions workflow manually from the main branch. When the deployments of both webapp and admin succeed, a release tag is created and pushed automatically on the deployed commit. If either one fails, no tag is created. That rule is a simple way to make the tag mean something: a tag exists only for a deployment where both halves are live.

The steps inside a deployment are build, then attaching the production domain with vercel promote, then verifying that the domain points at this deployment, and the script that does it lives at scripts/vercel-deploy-production.sh. A deploy started from the command line does not attach the production domain automatically, so the documentation is explicit that a deployment only counts as successful once the promote and the verification have both been done.

Tags are named release-YYYYMMDD-HHMMSS in Japan Standard Time, with release-20260911-153012 given as the example, and sorting them by name gives the deployment order. The commit currently in production can be found through the latest release tag.

```bash
git fetch --tags
git log -1 "$(git tag -l 'release-*' --sort=-refname | head -n 1)"
```

That pair of commands is the answer to a question every adopter of this project will eventually ask, and having it written down in the README is a small sign of care.

## AGPL terms, a CLA, and a licence label GitHub cannot read

The licence section states that the project is licensed under the GNU Affero General Public License v3.0, and the badge in the README shows the same thing. The licence file is at the root, and the documentation asks that appropriate attribution be displayed when the software is used, with the LICENSE file as the reference for the exact wording.

There is a wrinkle worth knowing about before you plan a deployment. The project's own metadata classifies the licence as a custom one that GitHub cannot categorise, while the README and the badge both name the AGPL version 3.0. Read the LICENSE file directly rather than relying on the label shown on the repository page.

The AGPL is the copyleft licence designed for network software, and this is a good example of why that distinction exists. If a modified version of this application is offered to users over a network, the source availability obligation follows the deployment. For a public-interest transparency platform that is entirely in keeping with the goal, and for an organisation embedding the application in a larger product it is a decision that needs making consciously.

Contributions carry a separate condition. The README states that contributing requires agreement to a Contributor License Agreement, with CLA.md in the root, alongside a CONTRIBUTING.md. There is a CODEOWNERS file as well, so the project expects review to be routed to named owners rather than to whoever happens to look available.

## The documentation is split into rules and snapshots, and the first release is old

The docs/ directory is classified rather than flat. The README explains that the project documentation is divided into the canonical documents that define the current rules and the snapshots in docs/old/ that record design notes from the time of implementation, with docs/README.md explaining how to read them. That is a good convention, and it also means a link to a document in old/ describes a system that may no longer exist. A newcomer who lands on a snapshot will draw wrong conclusions about the current architecture, so the reading guide matters more than usual here.

The other thing to know is the age of the code relative to the documentation. The only published release is v.1.0.0, tagged as the first release on 2025-10-01, while the last push to the main branch was on 2026-10-20. So the repository is being worked on, and the tag list still reflects a first release. The README also notes that the values shown in the application screenshot are not real values, which is a small but useful warning: do not treat the demo screen as a data sample.

The data/ directory holds sample data files, and the application itself is the only published surface. There is no indication of a public API or a bulk download of the underlying records, so anyone who wants the data itself has to use the dashboard or read the sample files.

## Conclusion

Marumie suits a team that wants a working reference for a public transparency dashboard with a separate import and administration layer, and it does not suit a reader who wants raw funding data as a download, since the project is an application rather than a published dataset. Before adopting it, read the AGPL-3.0 LICENSE file and the CLA.md, because the copyleft terms and the contributor agreement are both conditions of use here, and check docs/README.md to tell current rules from snapshots of the earlier design in docs/old/.

## FAQ

### What is Marumie and who develops it?

Marumie is an open source dashboard for political funding transparency, letting politicians and political organisations publish accounting data so citizens can understand the flow of money, with data imported from cloud accounting services such as MF Cloud and freee. It is developed by the Team Mirai Nagatacho engineering team.

### How do I run Marumie locally?

The root package.json provides a setup script that runs pnpm install and resets the database, and a dev script that starts the local Supabase instance and then runs the webapp and admin frontends together. The environment template points the database at the local Supabase Postgres port on 127.0.0.1, and the full setup steps are in docs/getting-started.md.

### What licence is Marumie released under?

The README states that the project is licensed under the GNU Affero General Public License v3.0 and asks that appropriate attribution be displayed when the software is used, with the terms in the LICENSE file. Contributing to the project additionally requires agreeing to the Contributor License Agreement in CLA.md.

### How do I find out which Marumie commit is running in production?

A release tag is created and pushed automatically on the deployed commit once both the webapp and admin deployments succeed, so the latest release tag identifies what is live. The README gives the commands git fetch --tags followed by git log -1 on the newest release- tag, and the tag names sort in deployment order.

## Sources

- [Issues](https://github.com/team-mirai/marumie/issues)
- [Project website](https://marumie.team-mir.ai)
- [README](https://github.com/team-mirai/marumie/blob/main/README.md)
- [Releases](https://github.com/team-mirai/marumie/releases)
- [team-mirai/marumie on GitHub](https://github.com/team-mirai/marumie)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/team-mirai-marumie
