[{"data":1,"prerenderedAt":777},["ShallowReactive",2],{"navigation_docs_en":3,"-en-development-installation":191,"-en-development-installation-surround":772},[4,61,127,171],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":60},"Guide","i-lucide-book-open","\u002Fen\u002Fguide","en\u002F1.guide",[10,15,20,25,30,35,40,45,50,55],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fguide\u002Fintroduction","en\u002F1.guide\u002F01.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Install the App","\u002Fen\u002Fguide\u002Finstallation","en\u002F1.guide\u002F02.installation","i-lucide-smartphone",{"title":21,"path":22,"stem":23,"icon":24},"Authentication","\u002Fen\u002Fguide\u002Fauth","en\u002F1.guide\u002F03.auth","i-lucide-lock",{"title":26,"path":27,"stem":28,"icon":29},"Wallets","\u002Fen\u002Fguide\u002Fwallets","en\u002F1.guide\u002F04.wallets","i-lucide-wallet",{"title":31,"path":32,"stem":33,"icon":34},"Categories","\u002Fen\u002Fguide\u002Fcategories","en\u002F1.guide\u002F05.categories","i-lucide-tags",{"title":36,"path":37,"stem":38,"icon":39},"Transactions","\u002Fen\u002Fguide\u002Ftransactions","en\u002F1.guide\u002F06.transactions","i-lucide-receipt",{"title":41,"path":42,"stem":43,"icon":44},"Transfers","\u002Fen\u002Fguide\u002Ftransfers","en\u002F1.guide\u002F07.transfers","i-lucide-arrow-left-right",{"title":46,"path":47,"stem":48,"icon":49},"Statistics","\u002Fen\u002Fguide\u002Fstatistics","en\u002F1.guide\u002F08.statistics","i-lucide-bar-chart-3",{"title":51,"path":52,"stem":53,"icon":54},"Theme","\u002Fen\u002Fguide\u002Ftheme","en\u002F1.guide\u002F09.theme","i-lucide-palette",{"title":56,"path":57,"stem":58,"icon":59},"Settings","\u002Fen\u002Fguide\u002Fsettings","en\u002F1.guide\u002F10.settings","i-lucide-settings",false,{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":60},"Development","i-lucide-code","\u002Fen\u002Fdevelopment","en\u002F2.development",[67,72,77,82,87,92,97,102,122],{"title":68,"path":69,"stem":70,"icon":71},"Installation","\u002Fen\u002Fdevelopment\u002Finstallation","en\u002F2.development\u002F01.installation","i-lucide-download",{"title":73,"path":74,"stem":75,"icon":76},"Codebase Graph","\u002Fen\u002Fdevelopment\u002Funderstand-anything","en\u002F2.development\u002F02.understand-anything","i-lucide-network",{"title":78,"path":79,"stem":80,"icon":81},"Offline & PWA","\u002Fen\u002Fdevelopment\u002Foffline","en\u002F2.development\u002F03.offline","i-lucide-wifi-off",{"title":83,"path":84,"stem":85,"icon":86},"Data Migration History","\u002Fen\u002Fdevelopment\u002Fmigration","en\u002F2.development\u002F04.migration","i-lucide-database",{"title":88,"path":89,"stem":90,"icon":91},"Deployment","\u002Fen\u002Fdevelopment\u002Fdeployment","en\u002F2.development\u002F05.deployment","i-lucide-rocket",{"title":93,"path":94,"stem":95,"icon":96},"Testing","\u002Fen\u002Fdevelopment\u002Ftesting","en\u002F2.development\u002F06.testing","i-lucide-flask-conical",{"title":98,"path":99,"stem":100,"icon":101},"Date Utilities","\u002Fen\u002Fdevelopment\u002Fdate-utilities","en\u002F2.development\u002F07.date-utilities","i-lucide-calendar",{"title":103,"path":104,"stem":105,"children":106,"page":60},"Ai Workflow","\u002Fen\u002Fdevelopment\u002Fai-workflow","en\u002F2.development\u002F08.ai-workflow",[107,112,117],{"title":108,"path":109,"stem":110,"icon":111},"Overview","\u002Fen\u002Fdevelopment\u002Fai-workflow\u002Foverview","en\u002F2.development\u002F08.ai-workflow\u002F01.overview","i-lucide-bot",{"title":113,"path":114,"stem":115,"icon":116},"Agents","\u002Fen\u002Fdevelopment\u002Fai-workflow\u002Fagents","en\u002F2.development\u002F08.ai-workflow\u002F02.agents","i-lucide-users",{"title":118,"path":119,"stem":120,"icon":121},"Skills","\u002Fen\u002Fdevelopment\u002Fai-workflow\u002Fskills","en\u002F2.development\u002F08.ai-workflow\u002F03.skills","i-lucide-lightbulb",{"title":123,"path":124,"stem":125,"icon":126},"Troubleshooting","\u002Fen\u002Fdevelopment\u002Ftroubleshooting","en\u002F2.development\u002F09.troubleshooting","i-lucide-life-buoy",{"title":128,"icon":129,"path":130,"stem":131,"children":132,"page":60},"Reference","i-lucide-file-code","\u002Fen\u002Freference","en\u002F3.reference",[133,138,142,147,152,156,161,166],{"title":134,"path":135,"stem":136,"icon":137},"Architecture","\u002Fen\u002Freference\u002Farchitecture","en\u002F3.reference\u002F01.architecture","i-lucide-boxes",{"title":139,"path":140,"stem":141,"icon":44},"Transaction Types","\u002Fen\u002Freference\u002Ftransaction-types","en\u002F3.reference\u002F02.transaction-types",{"title":143,"path":144,"stem":145,"icon":146},"Sync","\u002Fen\u002Freference\u002Fsync","en\u002F3.reference\u002F03.sync","i-lucide-refresh-cw",{"title":148,"path":149,"stem":150,"icon":151},"Offline-first","\u002Fen\u002Freference\u002Foffline-first","en\u002F3.reference\u002F04.offline-first","i-lucide-list-ordered",{"title":153,"path":154,"stem":155,"icon":121},"Technical Decisions","\u002Fen\u002Freference\u002Ftech-decisions","en\u002F3.reference\u002F05.tech-decisions",{"title":157,"path":158,"stem":159,"icon":160},"Validation Strategy","\u002Fen\u002Freference\u002Fvalidation-strategy","en\u002F3.reference\u002F06.validation-strategy","i-lucide-shield-check",{"title":162,"path":163,"stem":164,"icon":165},"What Changed Since Firebase","\u002Fen\u002Freference\u002Ffirebase-migration","en\u002F3.reference\u002F07.firebase-migration","i-lucide-hamburger",{"title":167,"path":168,"stem":169,"icon":170},"Performance","\u002Fen\u002Freference\u002Fperformance","en\u002F3.reference\u002F08.performance","i-lucide-gauge",{"title":172,"icon":173,"path":174,"stem":175,"children":176,"page":60},"Premium","i-lucide-star","\u002Fen\u002Fpremium","en\u002F4.premium",[177,181,186],{"title":108,"path":178,"stem":179,"icon":180},"\u002Fen\u002Fpremium\u002Foverview","en\u002F4.premium\u002F01.overview","i-lucide-layers",{"title":182,"path":183,"stem":184,"icon":185},"Telegram Bot","\u002Fen\u002Fpremium\u002Ftelegram-bot","en\u002F4.premium\u002F02.telegram-bot","i-lucide-send",{"title":187,"path":188,"stem":189,"icon":190},"AI Chat","\u002Fen\u002Fpremium\u002Fai-chat","en\u002F4.premium\u002F03.ai-chat","i-lucide-sparkles",{"id":192,"title":68,"body":193,"description":764,"extension":765,"links":766,"meta":767,"navigation":768,"path":69,"seo":769,"stem":70,"__hash__":771},"docs_en\u002Fen\u002F2.development\u002F01.installation.md",{"type":194,"value":195,"toc":747},"minimark",[196,201,239,242,559,563,570,703,707,743],[197,198,200],"h2",{"id":199},"requirements","Requirements",[202,203,204,215,223,231],"ul",{},[205,206,207,214],"li",{},[208,209,213],"a",{"href":210,"rel":211},"https:\u002F\u002Fnodejs.org",[212],"nofollow","Node.js"," v24.12.0 or later",[205,216,217,222],{},[208,218,221],{"href":219,"rel":220},"https:\u002F\u002Fpnpm.io",[212],"pnpm"," >= 11.1.2",[205,224,225,230],{},[208,226,229],{"href":227,"rel":228},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fcli",[212],"Supabase CLI"," (for local Supabase)",[205,232,233,238],{},[208,234,237],{"href":235,"rel":236},"https:\u002F\u002Fdocs.docker.com\u002Fget-docker\u002F",[212],"Docker"," (for Supabase and PowerSync)",[197,240,68],{"id":241},"installation",[243,244,245,250,287,291,303,307,311,327,389,412,416,423,429,443,448,487,498,503,527,531,543,551],"steps",{},[246,247,249],"h3",{"id":248},"clone-the-repository","Clone the repository",[251,252,258],"pre",{"className":253,"code":254,"filename":255,"language":256,"meta":257,"style":257},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git clone https:\u002F\u002Fgithub.com\u002Filkome\u002Ffinapp.git\ncd finapp\n","Terminal","bash","",[259,260,261,277],"code",{"__ignoreMap":257},[262,263,266,270,274],"span",{"class":264,"line":265},"line",1,[262,267,269],{"class":268},"sBMFI","git",[262,271,273],{"class":272},"sfazB"," clone",[262,275,276],{"class":272}," https:\u002F\u002Fgithub.com\u002Filkome\u002Ffinapp.git\n",[262,278,280,284],{"class":264,"line":279},2,[262,281,283],{"class":282},"s2Zo4","cd",[262,285,286],{"class":272}," finapp\n",[246,288,290],{"id":289},"install-dependencies","Install dependencies",[251,292,294],{"className":253,"code":293,"filename":255,"language":256,"meta":257,"style":257},"pnpm install\n",[259,295,296],{"__ignoreMap":257},[262,297,298,300],{"class":264,"line":265},[262,299,221],{"class":268},[262,301,302],{"class":272}," install\n",[246,304,306],{"id":305},"configure-environment-variables","Configure environment variables",[308,309,310],"p",{},"Copy the example env file and fill in your values:",[251,312,314],{"className":253,"code":313,"filename":255,"language":256,"meta":257,"style":257},"cp app\u002F.env.example app\u002F.env\n",[259,315,316],{"__ignoreMap":257},[262,317,318,321,324],{"class":264,"line":265},[262,319,320],{"class":268},"cp",[262,322,323],{"class":272}," app\u002F.env.example",[262,325,326],{"class":272}," app\u002F.env\n",[251,328,331],{"className":253,"code":329,"filename":330,"language":256,"meta":257,"style":257},"VITE_SUPABASE_URL=http:\u002F\u002Flocalhost:54321\nVITE_SUPABASE_ANON_KEY=\u003Canon key from supabase start output>\nVITE_POWERSYNC_URL=http:\u002F\u002Flocalhost:8080\n","app\u002F.env",[259,332,333,346,378],{"__ignoreMap":257},[262,334,335,339,343],{"class":264,"line":265},[262,336,338],{"class":337},"sTEyZ","VITE_SUPABASE_URL",[262,340,342],{"class":341},"sMK4o","=",[262,344,345],{"class":272},"http:\u002F\u002Flocalhost:54321\n",[262,347,348,351,354,357,360,363,366,369,372,375],{"class":264,"line":279},[262,349,350],{"class":337},"VITE_SUPABASE_ANON_KEY",[262,352,353],{"class":341},"=\u003C",[262,355,356],{"class":272},"anon",[262,358,359],{"class":268}," key",[262,361,362],{"class":272}," from",[262,364,365],{"class":272}," supabase",[262,367,368],{"class":272}," start",[262,370,371],{"class":272}," outpu",[262,373,374],{"class":337},"t",[262,376,377],{"class":341},">\n",[262,379,381,384,386],{"class":264,"line":380},3,[262,382,383],{"class":337},"VITE_POWERSYNC_URL",[262,385,342],{"class":341},[262,387,388],{"class":272},"http:\u002F\u002Flocalhost:8080\n",[308,390,391,392,395,396,399,400,402,403,399,406,408,409,411],{},"For local development, ",[259,393,394],{},"supabase start"," prints the ",[259,397,398],{},"API URL"," (use as ",[259,401,338],{},") and ",[259,404,405],{},"anon key",[259,407,350],{},"). ",[259,410,383],{}," is the PowerSync service started in the next step.",[246,413,415],{"id":414},"start-the-local-backend","Start the local backend",[308,417,418,419,422],{},"Run these three commands once from the ",[259,420,421],{},"app\u002F"," directory. After the initial setup you only need to start the containers again if they are stopped.",[308,424,425],{},[426,427,428],"strong",{},"1. Start Supabase (Postgres + Auth on port 54321):",[251,430,433],{"className":253,"code":431,"filename":432,"language":256,"meta":257,"style":257},"supabase start\n","Terminal - from app\u002F",[259,434,435],{"__ignoreMap":257},[262,436,437,440],{"class":264,"line":265},[262,438,439],{"class":268},"supabase",[262,441,442],{"class":272}," start\n",[308,444,445],{},[426,446,447],{},"2. Apply the PowerSync replication setup:",[251,449,451],{"className":253,"code":450,"filename":432,"language":256,"meta":257,"style":257},"docker exec -i supabase_db_app psql -U postgres -d postgres \u003C supabase\u002Fpowersync_setup.sql\n",[259,452,453],{"__ignoreMap":257},[262,454,455,458,461,464,467,470,473,476,479,481,484],{"class":264,"line":265},[262,456,457],{"class":268},"docker",[262,459,460],{"class":272}," exec",[262,462,463],{"class":272}," -i",[262,465,466],{"class":272}," supabase_db_app",[262,468,469],{"class":272}," psql",[262,471,472],{"class":272}," -U",[262,474,475],{"class":272}," postgres",[262,477,478],{"class":272}," -d",[262,480,475],{"class":272},[262,482,483],{"class":341}," \u003C",[262,485,486],{"class":272}," supabase\u002Fpowersync_setup.sql\n",[308,488,489,490,493,494,497],{},"This creates a ",[259,491,492],{},"powersync_role"," with replication privileges and a ",[259,495,496],{},"powersync"," publication scoped to the five Finapp tables.",[308,499,500],{},[426,501,502],{},"3. Start the PowerSync service (port 8080):",[251,504,506],{"className":253,"code":505,"filename":432,"language":256,"meta":257,"style":257},"docker compose -f powersync\u002Fdocker-compose.yaml up -d\n",[259,507,508],{"__ignoreMap":257},[262,509,510,512,515,518,521,524],{"class":264,"line":265},[262,511,457],{"class":268},[262,513,514],{"class":272}," compose",[262,516,517],{"class":272}," -f",[262,519,520],{"class":272}," powersync\u002Fdocker-compose.yaml",[262,522,523],{"class":272}," up",[262,525,526],{"class":272}," -d\n",[246,528,530],{"id":529},"start-the-development-server","Start the development server",[251,532,534],{"className":253,"code":533,"filename":255,"language":256,"meta":257,"style":257},"pnpm dev\n",[259,535,536],{"__ignoreMap":257},[262,537,538,540],{"class":264,"line":265},[262,539,221],{"class":268},[262,541,542],{"class":272}," dev\n",[308,544,545,546,550],{},"The app will be available at ",[208,547,548],{"href":548,"rel":549},"http:\u002F\u002Flocalhost:3050",[212],".",[308,552,553,554,558],{},"A design system playground is available at ",[208,555,556],{"href":556,"rel":557},"http:\u002F\u002Flocalhost:3050\u002Fdev",[212]," during development (hidden in production).",[197,560,562],{"id":561},"google-sign-in-optional","Google sign-in (optional)",[308,564,565,566,569],{},"The login screen has a ",[426,567,568],{},"Sign in with Google"," button. Email\u002Fpassword works without any of this - set up Google only to test that flow locally.",[243,571,572,576,589,597,603,637,660,664,683],{},[246,573,575],{"id":574},"create-a-google-oauth-client","Create a Google OAuth client",[308,577,578,579,584,585,588],{},"In the ",[208,580,583],{"href":581,"rel":582},"https:\u002F\u002Fconsole.cloud.google.com\u002Fapis\u002Fcredentials",[212],"Google Cloud Console",", create an ",[426,586,587],{},"OAuth 2.0 Client ID"," (Web application) and add the local Supabase callback as an authorized redirect URI:",[251,590,595],{"className":591,"code":593,"language":594,"meta":257},[592],"language-text","http:\u002F\u002F127.0.0.1:54321\u002Fauth\u002Fv1\u002Fcallback\n","text",[259,596,593],{"__ignoreMap":257},[246,598,600,601],{"id":599},"add-the-credentials-to-appenv","Add the credentials to ",[259,602,330],{},[251,604,606],{"className":253,"code":605,"filename":330,"language":256,"meta":257,"style":257},"SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID=\u003Cclient id>\nSUPABASE_AUTH_EXTERNAL_GOOGLE_SECRET=\u003Cclient secret>\n",[259,607,608,623],{"__ignoreMap":257},[262,609,610,613,615,618,621],{"class":264,"line":265},[262,611,612],{"class":337},"SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID",[262,614,353],{"class":341},[262,616,617],{"class":272},"client",[262,619,620],{"class":268}," id",[262,622,377],{"class":337},[262,624,625,628,630,632,635],{"class":264,"line":279},[262,626,627],{"class":337},"SUPABASE_AUTH_EXTERNAL_GOOGLE_SECRET",[262,629,353],{"class":341},[262,631,617],{"class":272},[262,633,634],{"class":268}," secret",[262,636,377],{"class":337},[308,638,639,640,643,644,647,648,651,652,655,656,659],{},"The Supabase CLI loads ",[259,641,642],{},".env"," from the directory you run it in. These feed ",[259,645,646],{},"env()"," in ",[259,649,650],{},"app\u002Fsupabase\u002Fconfig.toml"," and are ",[426,653,654],{},"not"," exposed to the client (no ",[259,657,658],{},"VITE_"," prefix).",[246,661,663],{"id":662},"restart-supabase","Restart Supabase",[251,665,667],{"className":253,"code":666,"filename":432,"language":256,"meta":257,"style":257},"supabase stop && supabase start\n",[259,668,669],{"__ignoreMap":257},[262,670,671,673,676,679,681],{"class":264,"line":265},[262,672,439],{"class":268},[262,674,675],{"class":272}," stop",[262,677,678],{"class":341}," &&",[262,680,365],{"class":268},[262,682,442],{"class":272},[308,684,685,686,689,690,693,694,697,698,647,700,550],{},"The Google provider is already enabled in ",[259,687,688],{},"config.toml"," (",[259,691,692],{},"[auth.external.google]",", ",[259,695,696],{},"skip_nonce_check = true"," for local), with the dev origin ",[259,699,548],{},[259,701,702],{},"additional_redirect_urls",[197,704,706],{"id":705},"production-build","Production Build",[708,709,710,723],"code-group",{},[251,711,714],{"className":253,"code":712,"filename":713,"language":256,"meta":257,"style":257},"pnpm build\n","SPA",[259,715,716],{"__ignoreMap":257},[262,717,718,720],{"class":264,"line":265},[262,719,221],{"class":268},[262,721,722],{"class":272}," build\n",[251,724,727],{"className":253,"code":725,"filename":726,"language":256,"meta":257,"style":257},"pnpm generate\npnpm preview\n","Static",[259,728,729,736],{"__ignoreMap":257},[262,730,731,733],{"class":264,"line":265},[262,732,221],{"class":268},[262,734,735],{"class":272}," generate\n",[262,737,738,740],{"class":264,"line":279},[262,739,221],{"class":268},[262,741,742],{"class":272}," preview\n",[744,745,746],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}",{"title":257,"searchDepth":279,"depth":279,"links":748},[749,750,757,763],{"id":199,"depth":279,"text":200},{"id":241,"depth":279,"text":68,"children":751},[752,753,754,755,756],{"id":248,"depth":380,"text":249},{"id":289,"depth":380,"text":290},{"id":305,"depth":380,"text":306},{"id":414,"depth":380,"text":415},{"id":529,"depth":380,"text":530},{"id":561,"depth":279,"text":562,"children":758},[759,760,762],{"id":574,"depth":380,"text":575},{"id":599,"depth":380,"text":761},"Add the credentials to app\u002F.env",{"id":662,"depth":380,"text":663},{"id":705,"depth":279,"text":706},"Get started with Finapp - clone, configure env vars, start the local backend, and run the dev server.","md",null,{},{"icon":71},{"title":68,"description":770},"How to install and run Finapp locally with Supabase and PowerSync.","-FnNreDWu67X-NCEb2yx2T3XDgX3JURSHkcSFi1aaBw",[773,775],{"title":56,"path":57,"stem":58,"description":774,"icon":59,"children":-1},"Configure base currency, language, demo mode, exchange rates, and data deletion in Finapp.",{"title":73,"path":74,"stem":75,"description":776,"icon":76,"children":-1},"Interactive knowledge graph of the Finapp codebase generated by the understand-anything plugin.",1782114342942]