Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
Track your money across bank, mobile money and cash, see spending until payday
AI summary · website content
FinanceTypeScript · CSSGitHub @tiemouie01OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Misi is a cycle-based personal finance app built with TanStack Start, Convex, and Better Auth.
To run this application:
pnpm install
cp .env.example .env.local
pnpm dev
Build and run the Nitro server locally with:
pnpm build
node .output/server/index.mjs
The production artifact is .output/server/index.mjs, not dist/server.
The public Convex URL is baked into the server bundle during the build, while
runtime values may still override it when explicitly configured.
Set VITE_CONVEX_URL in .env.local to the public *.convex.cloud URL for
the Convex deployment you are using. VITE_CONVEX_SITE_URL is optional when
that URL follows Convex's standard *.convex.cloud/*.convex.site naming.
For local Convex development, set CONVEX_DEPLOYMENT to the deployment
selected by pnpm dlx convex dev and run:
pnpm dlx convex dev
CONVEX_DEPLOYMENT is a local development setting. Do not use it as the
Vercel deploy credential.
Authentication is hosted by the Convex Better Auth component. Set these
variables on the Convex deployment, not only in the web app's .env.local:
pnpm dlx convex env set SITE_URL http://localhost:3000
pnpm dlx convex env set BETTER_AUTH_SECRET '<a long random secret>'
SITE_URL must be the public origin where Misi is served. For production,
set it to the production HTTPS origin. Generate a different secret for each
deployment and keep it out of source control.
Google sign-in is optional. Configure both variables together, or leave both unset:
pnpm dlx convex env set GOOGLE_CLIENT_ID '<client id>'
pnpm dlx convex env set GOOGLE_CLIENT_SECRET '<client secret>'
The Google OAuth redirect URI is
<SITE_URL>/api/auth/callback/google. Set VITE_GOOGLE_AUTH_ENABLED=true in
the web app only after both Google credentials are present on Convex.
Set VITE_POSTHOG_KEY in .env.local to enable analytics. The default host is
https://us.i.posthog.com; set VITE_POSTHOG_HOST for another PostHog Cloud
region or a self-hosted instance.
vercel.json uses pnpm run vercel-build. That script deploys the Convex
functions and then builds the app, so configure a Convex deploy key in Vercel:
CONVEX_DEPLOY_KEY=prod:... # production
CONVEX_DEPLOY_KEY=preview:... # preview
The key must start with prod: or preview:. Development keys are rejected.
Do not set CONVEX_DEPLOYMENT in Vercel; it selects user-token auth and is not
the CI credential used by the build script. Configure Convex deployment
variables such as SITE_URL, BETTER_AUTH_SECRET, and the optional Google
credentials through the Convex dashboard or convex env set.
Run the full local checks before shipping:
pnpm test
pnpm typecheck
pnpm lint
pnpm check
pnpm build
This project uses TanStack Router with file-based routing. Routes are managed as files in src/routes.
To add a new route to your application just add a new file in the ./src/routes directory.
TanStack will automatically generate the content of the route file for you.
Now that you have two routes you can use a Link component to navigate between them.
To use SPA (Single Page Application) navigation you will need to import the Link component from @tanstack/react-router.
import { Link } from '@tanstack/react-router'
Then anywhere in your JSX you can use it like so:
<Link to="/about">About</Link>
This will create a link that will navigate to the /about route.
More information on the Link component can be found in the Link documentation.
In the File Based Routing setup the layout is located in src/routes/__root.tsx. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you render {children} in the shellComponent.
Here is an example layout that includes a header:
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'My App' },
],
}),
shellComponent: ({ children }) => (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<header>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
</header>
{children}
<Scripts />
</body>
</html>
),
})
More information on layouts can be found in the Layouts documentation.
TanStack Start provides server functions that allow you to write server-side code that seamlessly integrates with your client components.
import { createServerFn } from '@tanstack/react-start'
const getServerTime = createServerFn({
method: 'GET',
}).handler(async () => {
return new Date().toISOString()
})
// Use in a component
function MyComponent() {
const [time, setTime] = useState('')
useEffect(() => {
getServerTime().then(setTime)
}, [])
return <div>Server time: {time}</div>
}
You can create API routes by using the server property in your route definitions:
import { createFileRoute } from '@tanstack/react-router'
import { json } from '@tanstack/react-start'
export const Route = createFileRoute('/api/hello')({
server: {
handlers: {
GET: () => json({ message: 'Hello, World!' }),
},
},
})
There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the loader functionality built into TanStack Router to load the data for a route before it's rendered.
For example:
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/people')({
loader: async () => {
const response = await fetch('https://swapi.dev/api/people')
return response.json()
},
component: PeopleComponent,
})
function PeopleComponent() {
const data = Route.useLoaderData()
return (
<ul>
{data.results.map((person) => (
<li key={person.name}>{person.name}</li>
))}
</ul>
)
}
Loaders simplify your data fetching logic dramatically. Check out more information in the Loader documentation.
You can learn more about all of the offerings from TanStack in the TanStack documentation.
For TanStack Start specific documentation, visit TanStack Start.