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.