From 85fd6c091044ae0e6ce3a17a17bc61e2164bed7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vi=CC=81ctor=20Falco=CC=81n?= Date: Wed, 26 Nov 2025 12:28:24 +0100 Subject: [PATCH] Add README.md and update .env.example for HTTPS URL --- .env.example | 2 +- README.md | 92 +++++++++++++++++++++++++ composer.json | 4 +- package-lock.json | 170 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 265 insertions(+), 3 deletions(-) create mode 100644 README.md diff --git a/.env.example b/.env.example index 339471ce..6426f2c9 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ APP_NAME=Laravel APP_ENV=local APP_KEY= APP_DEBUG=true -APP_URL=http://localhost +APP_URL=https://whispermoney.test APP_LOCALE=en APP_FALLBACK_LOCALE=en diff --git a/README.md b/README.md new file mode 100644 index 00000000..09576386 --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +

+ Whisper Money +

+ +# Whisper Money + +**The most secure way to understand your finances.** + +Whisper Money is a privacy-first personal finance application that helps you track, categorize, and understand your spendingβ€”all while keeping your financial data encrypted and secure. + +## Features + +- πŸ” **End-to-end encryption** β€” Your financial data stays private +- 🏦 **Bank account management** β€” Track multiple accounts in one place +- πŸ“Š **Transaction categorization** β€” Automatic and manual categorization +- πŸ€– **Automation rules** β€” Set up rules to auto-categorize transactions +- πŸ“ˆ **Financial insights** β€” Understand your spending patterns + +## Tech Stack + +- **Backend:** Laravel 12, PHP 8.4 +- **Frontend:** React 19, Inertia.js v2, TypeScript +- **Styling:** Tailwind CSS v4 +- **Database:** MySQL +- **Cache/Queue:** Redis +- **Testing:** Pest v4 + +## Running Locally + +### Prerequisites + +- Docker & Docker Compose +- Composer +- Node.js / Bun + +### Setup + +1. **Clone the repository:** + +```bash +git clone https://github.com/your-username/whisper_money.git +cd whisper_money +``` + +2. **Copy the environment file:** + +```bash +cp .env.example .env +``` + +3. **Start the Docker services:** + +```bash +docker compose up -d +``` + +4. **Install dependencies and setup the application:** + +```bash +composer setup +``` + +5. **Start the development server:** + +```bash +composer run dev +``` + +This will concurrently start: + +- PHP development server +- Queue worker +- Log viewer (Pail) +- Vite dev server + +The application will be available at `https://whispermoney.test`. + +## License + +This project is licensed under the **Creative Commons Attribution-NonCommercial 4.0 International License (CC BY-NC 4.0)**. + +You are free to: + +- **Share** β€” copy and redistribute the material in any medium or format +- **Adapt** β€” remix, transform, and build upon the material + +Under the following terms: + +- **Attribution** β€” You must give appropriate credit, provide a link to the license, and indicate if changes were made +- **NonCommercial** β€” You may not use the material for commercial purposes + +For more details, see the [full license](https://creativecommons.org/licenses/by-nc/4.0/). diff --git a/composer.json b/composer.json index 16a0910e..1e6cc4c7 100644 --- a/composer.json +++ b/composer.json @@ -46,8 +46,8 @@ "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"", "@php artisan key:generate", "@php artisan migrate --force", - "npm install", - "npm run build" + "bun install", + "bun run build" ], "dev": [ "Composer\\Config::disableProcessTimeout", diff --git a/package-lock.json b/package-lock.json index b7b2f045..6172a025 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,11 +11,13 @@ "@radix-ui/react-avatar": "^1.1.3", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-collapsible": "^1.1.3", + "@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-navigation-menu": "^1.2.5", "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.8", "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-separator": "^1.1.8", @@ -33,6 +35,8 @@ "cmdk": "^1.1.1", "concurrently": "^9.0.1", "date-fns": "^4.1.0", + "dexie": "^4.2.1", + "dexie-react-hooks": "^4.2.0", "globals": "^15.14.0", "input-otp": "^1.4.2", "json-logic-js": "^2.0.5", @@ -40,6 +44,7 @@ "lucide-react": "^0.553.0", "react": "^19.2.0", "react-dom": "^19.2.0", + "sonner": "^2.0.7", "tailwind-merge": "^3.0.1", "tailwindcss": "^4.0.0", "tw-animate-css": "^1.4.0", @@ -59,6 +64,7 @@ "eslint-config-prettier": "^10.0.1", "eslint-plugin-react": "^7.37.3", "eslint-plugin-react-hooks": "^7.0.0", + "playwright": "^1.57.0", "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-tailwindcss": "^0.6.11", @@ -1332,6 +1338,34 @@ } } }, + "node_modules/@radix-ui/react-context-menu": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-dialog": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", @@ -1794,6 +1828,68 @@ } } }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz", + "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-radio-group": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", @@ -4062,6 +4158,23 @@ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" }, + "node_modules/dexie": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/dexie/-/dexie-4.2.1.tgz", + "integrity": "sha512-Ckej0NS6jxQ4Po3OrSQBFddayRhTCic2DoCAG5zacOfOVB9P2Q5Xc5uL/nVa7ZVs+HdMnvUPzLFCB/JwpB6Csg==", + "license": "Apache-2.0" + }, + "node_modules/dexie-react-hooks": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dexie-react-hooks/-/dexie-react-hooks-4.2.0.tgz", + "integrity": "sha512-u7KqTX9JpBQK8+tEyA9X0yMGXlSCsbm5AU64N6gjvGk/IutYDpLBInMYEAEC83s3qhIvryFS+W+sqLZUBEvePQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@types/react": ">=16", + "dexie": ">=4.2.0-alpha.1 <5.0.0", + "react": ">=16" + } + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -6221,6 +6334,53 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -6934,6 +7094,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",