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.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 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.