26 - Add nix-shell and rewrite README

This commit is contained in:
myrmidex 2026-05-01 20:59:56 +02:00
parent 7c19684159
commit ba6bb62e73
2 changed files with 221 additions and 122 deletions

195
README.md
View file

@ -1,157 +1,108 @@
<div align="center"> <div align="center">
# 📈 incr # incr
**A minimalist investment tracker for VWCE shares with milestone-driven progress** **A minimalist counter with milestone-driven progress**
*Track your portfolio growth with visual progress indicators and milestone reinforcement* *Track anything you accumulate — with visual progress and milestone reinforcement*
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Docker](https://img.shields.io/badge/Docker-Ready-2496ED?logo=docker&logoColor=white)](https://www.docker.com/)
[![Laravel](https://img.shields.io/badge/Laravel-12-FF2D20?logo=laravel&logoColor=white)](https://laravel.com/) [![Laravel](https://img.shields.io/badge/Laravel-12-FF2D20?logo=laravel&logoColor=white)](https://laravel.com/)
[![React](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=black)](https://reactjs.org/) [![React](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=black)](https://reactjs.org/)
---
**[Introduction](#introduction) • [Features](#features) • [Tech Stack](#tech-stack) • [Getting Started](#getting-started) • [Development](#development) • [Contributing](#contributing) • [License](#license)**
---
</div> </div>
## Introduction ## About
Incr is a minimalist, one-page investment tracking application designed specifically for VWCE (Vanguard FTSE All-World UCITS ETF) shareholders. It combines the satisfaction of visual progress tracking with practical portfolio management, featuring a distinctive LED-style digital display and milestone-based goal setting. incr is a minimalist, self-hosted tracking app. Pick something you want to accumulate — shares, books, workouts, anything — log your progress, and watch milestones fall.
The application emphasizes simplicity and focus, providing just what you need to track your investment journey without overwhelming complexity. It features a distinctive LED-style digital display, configurable milestones, and optional price tracking.
## Features ## Features
- **LED-style display**: Large red digital counter showing current share count - **LED-style display** — large red digital counter
- **Progress tracking**: Visual progress bar toward configurable milestones - **Milestone tracking** — set targets, cycle through them as you progress
- **Purchase management**: Add and track share purchases with historical data - **Purchase logging** — add entries with date and optional price
- **Financial insights**: Portfolio value and withdrawal estimates - **Price tracking** — optional; log a current price to see portfolio value and P/L
- **Milestone cycling**: Track progress toward multiple investment goals (1500→3000→4500→6000) - **Self-hosted** — your data stays on your server
## Tech Stack ## Tech Stack
- **Backend**: Laravel 12 (PHP 8.2+) with MySQL database - **Backend**: Laravel 12 (PHP 8.3+) with MySQL
- **Frontend**: React 19 + TypeScript with Inertia.js - **Frontend**: React 19 + TypeScript with Inertia.js
- **Styling**: Tailwind CSS 4 with shadcn/ui components - **Styling**: Tailwind CSS 4 with shadcn/ui components
- **Deployment**: Docker with multi-stage builds - **Deployment**: Docker / Podman with multi-stage builds
## Getting Started ## Self-hosting
### Quick Start (Production) ```yaml
# docker-compose.yml
services:
app:
image: forge.lvl0.xyz/lvl0/incr:latest
container_name: incr-app
restart: unless-stopped
environment:
- APP_ENV=production
- APP_DEBUG=false
- APP_KEY=base64:YOUR_APP_KEY_HERE
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_PORT=3306
- DB_DATABASE=incr
- DB_USERNAME=incr_user
- DB_PASSWORD=change_me
ports:
- "5001:80"
depends_on:
db:
condition: service_healthy
networks:
- incr-network
#### Docker db:
image: mysql:8.0
container_name: incr-db
restart: unless-stopped
environment:
- MYSQL_DATABASE=incr
- MYSQL_USER=incr_user
- MYSQL_PASSWORD=change_me
- MYSQL_ROOT_PASSWORD=change_me_root
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "incr_user", "-pchange_me"]
timeout: 10s
retries: 10
interval: 10s
start_period: 10s
networks:
- incr-network
Clone the repository and run with Docker Compose: networks:
incr-network:
driver: bridge
```bash volumes:
git clone https://github.com/your-username/incr.git db_data:
cd incr
``` ```
Run the application using the provided docker-compose configuration: Generate an app key with: `php artisan key:generate --show`
The app will be available at `http://localhost:5001`.
## Development
Requires [Nix](https://nixos.org/download/). Enter the dev shell:
```bash ```bash
# Using Docker Compose nix-shell
docker-compose -f docker/production/docker-compose.yml up --build dev-up
# Or using Podman Compose
podman-compose -f docker/production/docker-compose.yml up --build
``` ```
The application will be available at `http://localhost:5001`. Available commands inside the shell: `dev-up`, `dev-down`, `dev-rebuild`, `dev-logs`, `dev-shell`, `dev-artisan`, `dev-composer`.
### Development
#### Local Development Setup
**Option 1: Laravel Sail (Docker)**
For local development with Laravel Sail:
```bash
# Install Laravel Sail
composer install
sail artisan sail:install
# Start development environment
sail up -d
# Install frontend dependencies and build assets
npm install
npm run dev
# Run migrations
sail artisan migrate
```
**Option 2: Podman Development**
For Fedora Atomic or other Podman-based systems:
```bash
# Quick start with helper script
bash docker/dev/podman/start-dev.sh
# Or manually:
# Install podman-compose if not available
pip3 install --user podman-compose
# Start development environment
podman-compose -f docker/dev/podman/docker-compose.yml up -d
# Run migrations
podman exec incr-dev-app php artisan migrate
```
**Option 3: Sail with Podman (Compatibility Layer)**
To use Laravel Sail commands with Podman:
```bash
# Source the alias script
source docker/dev/podman/podman-sail-alias.sh
# Now you can use sail commands as normal
sail up -d
sail artisan migrate
sail npm run dev
```
The development server will be available at `http://localhost` with hot reload enabled.
## Project Structure
- `app/` - Laravel backend (controllers, models, services)
- `resources/js/` - React frontend components and pages
- `docker/production/` - Production Docker configuration
- `docker/dev/podman/` - Development Podman configuration
- `database/migrations/` - Database schema definitions
## Contributing
We welcome contributions to incr! Whether you're reporting bugs, suggesting features, or submitting pull requests, your input helps make this project better.
### How to Contribute
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
### Bug Reports
If you find a bug, please create an issue with:
- A clear description of the problem
- Steps to reproduce the issue
- Expected vs actual behavior
- Your environment details
## License ## License
This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details. GNU General Public License v3.0 — see [LICENSE](LICENSE).

148
shell.nix Normal file
View file

@ -0,0 +1,148 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [
# PHP and tools
php83
php83Packages.composer
# Node.js (needed for Tailwind CSS / Vite)
nodejs_22
# Container tools
podman
podman-compose
# Utilities
git
curl
gnumake
];
shellHook = ''
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)
export PODMAN_USERNS=keep-id
# Compose file location
COMPOSE_FILE="$PWD/docker/dev/podman/docker-compose.yml"
# ===================
# ALIASES
# ===================
alias pc='podman-compose -f $COMPOSE_FILE'
# ===================
# DEV COMMANDS
# ===================
dev-up() {
echo "Starting services..."
PODMAN_USERNS=keep-id podman-compose -f $COMPOSE_FILE up -d "$@"
echo ""
podman-compose -f $COMPOSE_FILE ps
echo ""
echo "App available at: http://localhost:8000"
}
dev-down() {
if [[ "$1" == "-v" ]]; then
echo "Stopping services and removing volumes..."
podman-compose -f $COMPOSE_FILE down -v
else
echo "Stopping services..."
podman-compose -f $COMPOSE_FILE down
fi
}
dev-restart() {
echo "Restarting services..."
podman-compose -f $COMPOSE_FILE restart "$@"
}
dev-rebuild() {
echo "Rebuilding services (down -v + up)..."
podman-compose -f $COMPOSE_FILE down -v
PODMAN_USERNS=keep-id podman-compose -f $COMPOSE_FILE up -d "$@"
echo ""
podman-compose -f $COMPOSE_FILE ps
echo ""
echo "App available at: http://localhost:8000"
}
dev-logs() {
podman-compose -f $COMPOSE_FILE logs -f app "$@"
}
dev-logs-db() {
podman-compose -f $COMPOSE_FILE logs -f db "$@"
}
dev-shell() {
podman-compose -f $COMPOSE_FILE exec app bash
}
dev-artisan() {
podman-compose -f $COMPOSE_FILE exec app php artisan "$@"
}
dev-composer() {
podman-compose -f $COMPOSE_FILE exec app composer "$@"
}
# ===================
# BUILD COMMANDS
# ===================
base-build() {
local image="forge.lvl0.xyz/lvl0/incr:latest"
if ! podman login --get-login forge.lvl0.xyz &>/dev/null; then
echo "Not logged in to forge.lvl0.xyz"
podman login forge.lvl0.xyz || return 1
fi
echo "Building image: $image"
if ! podman build -t "$image" -f Dockerfile .; then
echo "Build failed!"
return 1
fi
echo ""
echo "Pushing to registry..."
if ! podman push "$image"; then
echo "Push failed!"
return 1
fi
echo ""
echo "Done! Image pushed: $image"
}
# ===================
# WELCOME MESSAGE
# ===================
echo ""
echo "================================================="
echo " incr Dev Environment "
echo "================================================="
echo ""
echo " Podman: $(podman --version | cut -d' ' -f3)"
echo ""
echo "Commands:"
echo " dev-up [services] Start all or specific services"
echo " dev-down [-v] Stop services (-v removes volumes)"
echo " dev-rebuild Fresh start (down -v + up)"
echo " dev-restart Restart services"
echo " dev-logs Tail app logs"
echo " dev-logs-db Tail database logs"
echo " dev-shell Shell into app container"
echo " dev-artisan <cmd> Run artisan command"
echo " dev-composer <cmd> Run composer command"
echo " base-build Build and push image"
echo ""
echo "Services:"
echo " app Laravel http://localhost:8000"
echo " vite HMR http://localhost:5173"
echo " db MySQL localhost:3307"
echo ""
'';
}