base on null **🚨 NOTE: This codebase is no longer being maintained. The repo we're actively working on is located at [maybe-finance/maybe](https://github.com/maybe-finance/maybe).** --- ![](https://github.com/maybe-finance/maybe/assets/35243/79d97b31-7fad-4031-9e83-5005bc1d7fd0) # Maybe: Open-source personal finance app <b>Get involved: [Discord](https://link.maybe.co/discord) • [Website](https://maybe.co) • [Issues](https://github.com/maybe-finance/maybe/issues)</b> ## Backstory We spent the better part of 2021/2022 building a personal finance + wealth management app called, Maybe. Very full-featured, including an "Ask an Advisor" feature which connected users with an actual CFP/CFA to help them with their finances (all included in your subscription). The business end of things didn't work out, and so we shut things down mid-2023. We spent the better part of $1,000,000 building the app (employees + contractors, data providers/services, infrastructure, etc.). We're now reviving the product as a fully open-source project. The goal is to let you run the app yourself, for free, and use it to manage your own finances and eventually offer a hosted version of the app for a small monthly fee. ## End goal Ultimately we want to rebuild this so that you can self-host, but we also have plans to offer a hosted version for a fee. That means some decisions will be made that don't explicitly make sense for self-hosted but _do_ support the goal of us offering a for-pay hosted version. ## Features As a personal finance + wealth management app, Maybe has a lot of features. Here's a brief overview of some of the main ones... - Net worth tracking - Financial account syncing - Investment benchmarking - Investment portfolio allocation - Debt insights - Retirement forecasting + planning - Investment return simulation - Manual account/investment tracking And dozens upon dozens of smaller features. ## Getting started This is the current state of building the app. We're actively working to make this process much more streamlined! _You'll need Docker installed to run the app locally._ [Docker Desktop](https://www.docker.com/products/docker-desktop/) is an easy way to get started. First, copy the `.env.example` file to `.env`: ``` cp .env.example .env ``` Then, create a new secret using `openssl rand -base64 32` and populate `NEXTAUTH_SECRET` in your `.env` file with it. To enable transactional emails, you'll need to create a [Postmark](https://postmarkapp.com/) account and add your API key to your `.env` file (`NX_EMAIL_PROVIDER_API_TOKEN`) and set `NX_EMAIL_PROVIDER` to `postmark`. You can also set the from and reply-to email addresses (`NX_EMAIL_FROM_ADDRESS` and `NX_EMAIL_REPLY_TO_ADDRESS`). If you want to run the app without email, you can set `NX_EMAIL_PROVIDER_API_TOKEN` to a dummy value or leave `NX_EMAIL_PROVIDER` blank. We also support SMTP for sending emails, see information about configuring environment variables in the `.env.example` file. Maybe uses [Teller](https://teller.io/) for connecting financial accounts. To get started with Teller, you'll need to create an account. Once you've created an account: - Add your Teller application id to your `.env` file (`NEXT_PUBLIC_TELLER_APP_ID`). - Download your authentication certificates from Teller, create a `certs` folder in the root of the project, and place your certs in that directory. You should have both a `certificate.pem` and `private_key.pem`. **NEVER** check these files into source control, the `.gitignore` file will prevent the `certs/` directory from being added, but please double-check. - Set your `NEXT_PUBLIC_TELLER_ENV` and `NX_TELLER_ENV` to your desired environment. The default is `sandbox` which allows for testing with mock data. The login credentials for the sandbox environment are `username` and `password`. To connect to real financial accounts, you'll need to use the `development` environment. - Webhooks are not implemented yet, but you can populate the `NX_TELLER_SIGNING_SECRET` with the value from your Teller account. - We highly recommend checking out the [Teller docs](https://teller.io/docs) for more info. Then run the following pnpm commands: ```shell pnpm install pnpm run dev:services:all pnpm prisma:migrate:dev pnpm prisma:seed pnpm dev ``` ## Set Up Ngrok External data providers require HTTPS/SSL webhook URLs for sending data. To test this locally/during development, you will need to setup `ngrok`. 1. Visit [ngrok.com](https://ngrok.com/) 2. Create a free account 3. Visit [this page](https://dashboard.ngrok.com/get-started/your-authtoken) to access your auth token 4. Paste it into your `.env` file: `NGROK_AUTH_TOKEN=your_auth_token` You should claim your free static domain to avoid needing to change the URL each time you start/stop the server. To do so: 1. Visit the [domains](https://dashboard.ngrok.com/cloud-edge/domains) page 2. Click on Create Domain 3. Copy the domain and paste it into your `.env` file: `NGROK_DOMAIN=your_domain` That's it! As long as you run the project locally using `docker` with `pnpm dev:services:all` you'll be good to go. ## External data To pull market data in (for investments), you'll need a Polygon.io API key. You can get one for free [here](https://polygon.io/) and then add it to your `.env` file (`NX_POLYGON_API_KEY`). **Note:** If you're using the free "basic" plan, you'll need to manually sync stock tickers using the dev tools in the app the first time you run it. It will then be re-synced automatically every 24 hours. If you're using a paid tier, be sure to update your `.env` file with the correct tier (`NX_POLYGON_API_TIER`) and tickers and pricing will be synced automatically. ## Tech stack - Next.js - Tailwind - Node.js - Express - Postgres (w/ Timescale) ## Credits The original app was built by [Zach Gollwitzer](https://twitter.com/zg_dev), [Nick Arciero](https://www.narciero.com/) and [Tim Wilson](https://twitter.com/actualTimWilson), with design work by [Justin Farrugia](https://twitter.com/justinmfarrugia). ## Copyright & license Maybe is distributed under an [AGPLv3 license](https://github.com/maybe-finance/maybe-archive/blob/main/LICENSE). "Maybe" is a trademark of Maybe Finance, Inc. ", Assign "at most 3 tags" to the expected json: {"id":"7556","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"