{"id":49318028,"url":"https://github.com/ichramsyah/poros-webapp","last_synced_at":"2026-04-26T16:04:51.606Z","repository":{"id":344554811,"uuid":"1174631806","full_name":"ichramsyah/poros-webapp","owner":"ichramsyah","description":"Aplikasi pencatatan keuangan pribadi (Personal Finance Tracker) berbasis web yang dirancang sangat minimalis, difokuskan untuk penggunaan di handphone (mobile-first), cepat, dan mudah dipahami oleh siapapun.","archived":false,"fork":false,"pushed_at":"2026-03-18T23:04:54.000Z","size":1357,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-19T12:33:12.488Z","etag":null,"topics":["dompet","firebase","nextjs","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"https://tabung-menabung-webapp.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ichramsyah.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-06T17:00:37.000Z","updated_at":"2026-03-18T23:04:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ichramsyah/poros-webapp","commit_stats":null,"previous_names":["ichramsyah/tabung-menabung-webapp","ichramsyah/poros-webapp"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ichramsyah/poros-webapp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichramsyah%2Fporos-webapp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichramsyah%2Fporos-webapp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichramsyah%2Fporos-webapp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichramsyah%2Fporos-webapp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ichramsyah","download_url":"https://codeload.github.com/ichramsyah/poros-webapp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ichramsyah%2Fporos-webapp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32303179,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dompet","firebase","nextjs","tailwindcss","typescript"],"created_at":"2026-04-26T16:04:51.081Z","updated_at":"2026-04-26T16:04:51.600Z","avatar_url":"https://github.com/ichramsyah.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Poros 💸\n\n![License MIT](https://img.shields.io/badge/License-MIT-A3D11E) ![React 19](https://img.shields.io/badge/React-19-1E80C2) ![Next.js 15](https://img.shields.io/badge/Next.js-15-5FA02A) ![Deployed](https://img.shields.io/badge/Deployed-Yes-A3D11E)\n\n![Next.js](https://img.shields.io/badge/NEXT.JS-000000?style=for-the-badge\u0026logo=nextdotjs\u0026logoColor=white) ![React](https://img.shields.io/badge/REACT-20232A?style=for-the-badge\u0026logo=react\u0026logoColor=61DAFB) ![Tailwind CSS](https://img.shields.io/badge/TAILWIND%20CSS-0EA5E9?style=for-the-badge\u0026logo=tailwindcss\u0026logoColor=white) ![TypeScript](https://img.shields.io/badge/TYPESCRIPT-1F5B92?style=for-the-badge\u0026logo=typescript\u0026logoColor=white) ![Firebase](https://img.shields.io/badge/FIREBASE-FFCA28?style=for-the-badge\u0026logo=firebase\u0026logoColor=black) ![Google Gemini](https://img.shields.io/badge/GOOGLE%20GEMINI-4285F4?style=for-the-badge\u0026logo=googlegemini\u0026logoColor=white) \n![Shadcn UI](https://img.shields.io/badge/SHADCN%20UI-000000?style=for-the-badge\u0026logo=shadcnui\u0026logoColor=white) ![Date-FNS](https://img.shields.io/badge/DATE--FNS-20232A?style=for-the-badge) ![Lucide React](https://img.shields.io/badge/LUCIDE%20REACT-1E80C2?style=for-the-badge) ![Prettier](https://img.shields.io/badge/PRETTIER-1A2B34?style=for-the-badge\u0026logo=prettier\u0026logoColor=F7B93E)\n\n**Poros** is a _Personal Life OS_ and a web-based personal finance tracker assistant. Designed with a futuristic and minimalist aesthetic, it focuses on a _mobile-first_ experience that is fast, secure, and intuitive.\n\nBuilt with a modern _tech stack_, this application doesn't just record numbers—it is equipped with an **AI Transaction Analysis** feature that provides sharp financial advice tailored to your profile (age, target goals, \u0026 profession) and tracks your historical trends.\n\n## ✨ Core Features \u0026 Advantages\n\n- **Personal AI Assistant (Poros AI):** Powered by the Google Gemini API, the AI reads your monthly spending patterns, provides a _Financial Score_, detects fund leaks (_Top Leaks_), and offers praise as well as _Actionable Advice_ custom-tailored to your age and occupation. Supports month-over-month _Trend Analysis_.\n- **100% Free Server Efficiency (Lazy Evaluation):** AI queries are designed to run automatically only once when a new month is first opened, then locked in the local database. Supports manual _Regenerate_ feature.\n- **Fast Authentication:** Login using your Google account (Google Sign-In) handled via Firebase Authentication. Safe and practical.\n- **Lightning-Fast Recording:** A floating `+` button (Floating Action Button) that can be pressed anytime to record a new _expense_ instantly.\n- **Five-Star Design:** The _dashboard_ uses the Poppins font, neat Shadcn icons, dynamic progress bars, and interactive cursors with an exclusive purple gradient theme (`#441752`).\n- **Absolute Data Security:** Protected by multi-layered _Firestore Security Rules_ where data can only be accessed by the account owner.\n\n## 🛠️ Tech Stack\n\n- **Framework:** [Next.js](https://nextjs.org/) (App Router, Turbopack)\n- **Styling:** [Tailwind CSS v4](https://tailwindcss.com/)\n- **UI Components:** [Shadcn UI](https://ui.shadcn.com/)\n- **Icons:** [Lucide React](https://lucide.dev/)\n- **Backend \u0026 Database:** [Firebase SDK](https://firebase.google.com/) (Authentication \u0026 Firestore)\n- **AI Integration:** [@google/genai](https://www.npmjs.com/package/@google/genai) (Google Gemini 3 Flash)\n- **Typography:** [Google Fonts (Poppins)](https://fonts.google.com/specimen/Poppins)\n- **Date Utility:** [date-fns](https://date-fns.org/)\n\n## 🏗️ System Architecture (Poros AI)\n\nPoros is designed with a **Client-Side Heavy \u0026 Serverless AI Integration** architecture to suppress server costs down to nearly 100% free.\n\n### Workflow \u0026 Smart Execution (Lazy Evaluation)\n\n```mermaid\nsequenceDiagram\n    participant UI as Poros Interface (Client)\n    participant FB as Firebase Firestore\n    participant API as Next.js API (/analyze)\n    participant AI as Google Gemini 3 Flash\n\n    UI-\u003e\u003eFB: 1. User accesses \"History\" tab (Last month's data)\n    FB--\u003e\u003eUI: Returns Historical Profiles, Income \u0026 Budgets\n\n    UI-\u003e\u003eUI: Check AI Analysis Data State\n    alt Data Already Exists\n        FB--\u003e\u003eUI: 2. Return old JSON AI Analysis\n        UI-\u003e\u003eUI: Instantly displays Screen (0 API Call)\n    else Data Doesn't Exist (Or Force Regenerate)\n        UI-\u003e\u003eAPI: 3. POST: Sends all contexts (Nominals \u0026 Target)\n        API-\u003e\u003eAI: 4. Assembles Prompt \u0026 Calls Model\n    \n        Note right of API: Strict Prompt Rules:\u003cbr/\u003eThe Hard Numbers, Health Score,\u003cbr/\u003eSaving Rate, MVP Category,\u003cbr/\u003eComprehensive Summary.\n\n        AI--\u003e\u003eAPI: 5. Structured JSON Response\n        API--\u003e\u003eUI: Catches and Parses the AI JSON\n        \n        UI-\u003e\u003eFB: 6. Permanently saves with ID (UID_MonthYear)\n        UI-\u003e\u003eUI: Reactively Updates the AI Card View\n    end\n```\n\n### Execution Details:\n\n1. **State Management \u0026 Data Layer:**\n   - All daily transactions (`expenses`), monthly budget allocations (`budgets`), and profiles are stored specifically per user in **Firebase Firestore**. This data is read to the UI using a combination of _real-time listeners_ and _cached fetches_.\n\n2. **AI Analysis Trigger (Lazy Evaluation):**\n   - When a user opens the \"History\" tab for a certain month (e.g., February `2026-02`), the application checks the `ai_analysis` collection in Firestore.\n   - If the analysis document **does not exist** (and the month is in the past), the UI shows an _Interactive Loading Status_ and silently calls our single Next.js API Endpoint (`/api/analyze`).\n   - If it **already exists**, the application purely reads static JSON data from the database without calling Gemini at all.\n\n3. **Context Gathering \u0026 Prompt Engineering:**\n   - The application assembles a razor-sharp context: Total Income, Expenses, remaining Budget per drawer, _Age_, _Profession (Bio)_, _Target Goal (Life target)_, and even sucks in _Trend Data_ (income \u0026 expenses from 1 month prior).\n   - All this data is compiled into a _Strict JSON_ format instruction via the Next.js _Route Handler_ backend, then fired into the **Google Gemini 3 Flash API**.\n\n4. **Response Parsing \u0026 Deterministic Overwrite:**\n   - Gemini responds in a structured JSON pattern containing: Nominal Remaining Money, _Health Score_, _Saving Rate_, a comprehensive long conclusion (_Poros' Summary_), Top Leaks, Achievements (_Praise_), and _Actionable_ Advice towards the _Target Goal_.\n   - This JSON result is immediately caught by the Frontend and injected into the Firestore table via a _Deterministic ID_ (`UID_Year-Month`).\n   - This _Deterministic ID_ concept allows users at any time to forcefully press the \"Regenerate\" button to overwrite the old AI review if they have just corrected their financial report.\n\n## 🚀 Installation \u0026 Running Locally (Development)\n\nTo run this project locally on your computer, follow these steps:\n\n### 1. Clone Repository \u0026 Install Dependencies\n\nMake sure Node.js is installed. Open your _terminal_ and type:\n\n```bash\ngit clone https://github.com/ichramsyah/tabung-menabung-webapp.git\ncd tabung-menabung-webapp\nnpm install\n```\n\n### 2. Prepare Firebase (Required)\n\nThis application heavily relies on Firebase. You must create your own database service:\n\n1. Open [Firebase Console](https://console.firebase.google.com/) and create a new project.\n2. Enable the **Authentication** \u003e **Google Sign-In** feature.\n3. Enable the **Firestore Database** feature.\n4. Under **Project Settings**, get your \"Web App\" API Keys config.\n\n### 3. Configure Environment Variables\n\nCreate a file named `.env.local` next to _package.json_ (root), and insert your Firebase credentials along with your Gemini API Key:\n\n```env\nNEXT_PUBLIC_FIREBASE_API_KEY=\"AIzaSyA...\"\nNEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=\"id-project.firebaseapp.com\"\nNEXT_PUBLIC_FIREBASE_PROJECT_ID=\"id-project\"\nNEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=\"id-project.firebasestorage.app\"\nNEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=\"123456789\"\nNEXT_PUBLIC_FIREBASE_APP_ID=\"1:123456789:web:abcde\"\nGEMINI_API_KEY=\"AIzaSyA...\"\n```\n\n### 4. Setup Firestore Security Rules\n\nIn the Firebase Console, open the Firestore menu -\u003e **Rules** tab, then _copy-paste_ the rules below so your database is secure and operates normally:\n\n```javascript\nrules_version = '2';\nservice cloud.firestore {\n  match /databases/{database}/documents {\n    match /users/{userId} {\n      allow read, write: if request.auth != null \u0026\u0026 request.auth.uid == userId;\n    }\n    match /budgets/{budgetId} {\n      allow read, delete: if request.auth != null \u0026\u0026 request.auth.uid == resource.data.userId;\n      allow create, update: if request.auth != null \u0026\u0026 request.auth.uid == request.resource.data.userId;\n    }\n    match /expenses/{expenseId} {\n      allow read, delete: if request.auth != null \u0026\u0026 request.auth.uid == resource.data.userId;\n      allow create, update: if request.auth != null \u0026\u0026 request.auth.uid == request.resource.data.userId;\n    }\n    match /income/{incomeId} {\n      allow read, delete: if request.auth != null \u0026\u0026 request.auth.uid == resource.data.userId;\n      allow create, update: if request.auth != null \u0026\u0026 request.auth.uid == request.resource.data.userId;\n    }\n    match /ai_analysis/{analysisId} {\n      allow read, delete: if request.auth != null \u0026\u0026 request.auth.uid == resource.data.userId;\n      allow create, update: if request.auth != null \u0026\u0026 request.auth.uid == request.resource.data.userId;\n    }\n  }\n}\n```\n\n### 5. Running Server\n\nRun the _development_ server:\n\n```bash\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) in your browser!\n\n## 📦 Deployment Guide (Vercel)\n\nThis application is 100% _compatible_ to be directly _deployed_ for free to [Vercel](https://vercel.com).\n\n1. _Push_ this code to your Github account.\n2. Open Vercel and create a _New Project_ from that Github repository.\n3. **IMPORTANT:** Add all the keys (`NEXT_PUBLIC_FIREBASE_...` and `GEMINI_API_KEY`) from the `.env.local` stage to the **Environment Variables** column in the Vercel _dashboard settings_ before clicking the _Deploy_ button.\n\n---\n\n_Created with the help of a collaborative AI system - 2026._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fichramsyah%2Fporos-webapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fichramsyah%2Fporos-webapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fichramsyah%2Fporos-webapp/lists"}