Skip to content

Commit ad79e89

Browse files
committed
First draft, looking good
0 parents  commit ad79e89

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+9894
-0
lines changed

.cursor/plans/odin_wallet_application_d232ada8.plan.md

Lines changed: 503 additions & 0 deletions
Large diffs are not rendered by default.

.github/workflows/docker.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Build and Push Docker Image
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_NAME: ${{ github.repository }}
14+
15+
jobs:
16+
build-and-push:
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
20+
packages: write
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Docker Buildx
27+
uses: docker/setup-buildx-action@v3
28+
29+
- name: Log in to GitHub Container Registry
30+
if: github.event_name != 'pull_request'
31+
uses: docker/login-action@v3
32+
with:
33+
registry: ${{ env.REGISTRY }}
34+
username: ${{ github.actor }}
35+
password: ${{ secrets.GITHUB_TOKEN }}
36+
37+
- name: Extract metadata (tags, labels) for Docker
38+
id: meta
39+
uses: docker/metadata-action@v5
40+
with:
41+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
42+
tags: |
43+
type=ref,event=branch
44+
type=sha,prefix=
45+
type=raw,value=latest,enable={{is_default_branch}}
46+
47+
- name: Build and push Docker image
48+
uses: docker/build-push-action@v5
49+
with:
50+
context: .
51+
push: ${{ github.event_name != 'pull_request' }}
52+
tags: ${{ steps.meta.outputs.tags }}
53+
labels: ${{ steps.meta.outputs.labels }}
54+
cache-from: type=gha
55+
cache-to: type=gha,mode=max
56+
57+
- name: Output image digest
58+
if: github.event_name != 'pull_request'
59+
run: echo "Image pushed with digest ${{ steps.build.outputs.digest }}"

.gitignore

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Dependencies
2+
node_modules/
3+
vendor/
4+
5+
# Build outputs
6+
/frontend/dist/
7+
*.exe
8+
*.exe~
9+
*.dll
10+
*.so
11+
*.dylib
12+
13+
# Test binary
14+
*.test
15+
16+
# Output of go coverage tool
17+
*.out
18+
19+
# IDE
20+
.idea/
21+
.vscode/
22+
*.swp
23+
*.swo
24+
*~
25+
26+
# Environment files
27+
.env
28+
.env.local
29+
.env.*.local
30+
31+
# Data directory (SQLite database)
32+
data/
33+
*.db
34+
*.db-journal
35+
*.db-wal
36+
*.db-shm
37+
38+
# OS files
39+
.DS_Store
40+
Thumbs.db
41+
42+
# Logs
43+
*.log
44+
npm-debug.log*
45+
yarn-debug.log*
46+
yarn-error.log*
47+
48+
# Temporary files
49+
tmp/
50+
temp/

Dockerfile

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Stage 1: Build React frontend
2+
FROM node:20-alpine AS frontend
3+
4+
WORKDIR /app/frontend
5+
6+
# Copy package files
7+
COPY frontend/package*.json ./
8+
9+
# Install dependencies
10+
RUN npm ci
11+
12+
# Copy frontend source
13+
COPY frontend/ ./
14+
15+
# Build for production
16+
RUN npm run build
17+
18+
# Stage 2: Build Go backend
19+
FROM golang:1.21-alpine AS backend
20+
21+
# Install build dependencies for CGO (required by sqlite3)
22+
RUN apk add --no-cache gcc musl-dev
23+
24+
WORKDIR /app
25+
26+
# Copy go mod files
27+
COPY go.mod go.sum ./
28+
29+
# Download dependencies
30+
RUN go mod download
31+
32+
# Copy source code
33+
COPY . .
34+
35+
# Copy built frontend from previous stage
36+
COPY --from=frontend /app/frontend/dist ./frontend/dist
37+
38+
# Build the Go binary with CGO enabled for sqlite
39+
ENV CGO_ENABLED=1
40+
RUN go build -ldflags="-s -w" -o server cmd/server/main.go
41+
42+
# Stage 3: Production image
43+
FROM alpine:latest
44+
45+
# Install runtime dependencies for sqlite
46+
RUN apk add --no-cache ca-certificates libc6-compat
47+
48+
WORKDIR /app
49+
50+
# Create data directory for SQLite database
51+
RUN mkdir -p /app/data
52+
53+
# Copy built binary
54+
COPY --from=backend /app/server .
55+
56+
# Copy frontend dist
57+
COPY --from=backend /app/frontend/dist ./frontend/dist
58+
59+
# Set environment variables
60+
ENV PORT=8080
61+
ENV DB_PATH=/app/data/wallet.db
62+
63+
# Expose port
64+
EXPOSE 8080
65+
66+
# Health check
67+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
68+
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
69+
70+
# Run the server
71+
CMD ["./server"]

README.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Odin Wallet
2+
3+
A professional, mobile-first personal finance management application built with Go and React.
4+
5+
![Odin Wallet](https://img.shields.io/badge/Odin-Wallet-DDE61F?style=for-the-badge&logo=wallet&logoColor=0F1822)
6+
7+
## Features
8+
9+
- **Multi-user Support**: Secure registration and authentication with session-based cookies
10+
- **Multiple Account Types**: Cash, Debit Card, Credit Card, Loan, Savings, Investment
11+
- **Transaction Tracking**: Categorized transactions with detailed history
12+
- **Financial Overview**: Assets vs Liabilities dashboard with net worth calculation
13+
- **Multi-currency Support**: Track accounts in different currencies
14+
- **Mobile-first Design**: Responsive UI optimized for mobile and desktop
15+
16+
## Tech Stack
17+
18+
- **Backend**: Go with Chi router and SQLite
19+
- **Frontend**: React 18 + Vite + TailwindCSS + Framer Motion
20+
- **Deployment**: Docker with GitHub Actions CI/CD
21+
22+
## Development Setup
23+
24+
### Prerequisites
25+
26+
- Go 1.21+
27+
- Node.js 20+
28+
- npm or pnpm
29+
30+
### Quick Start
31+
32+
```bash
33+
# Clone the repository
34+
git clone https://github.com/kengru/odin-wallet.git
35+
cd odin-wallet
36+
37+
# Start the backend (from root directory)
38+
go mod download
39+
go run cmd/server/main.go
40+
41+
# In a separate terminal, start the frontend
42+
cd frontend
43+
npm install
44+
npm run dev
45+
```
46+
47+
- Backend runs on `http://localhost:8080`
48+
- Frontend dev server runs on `http://localhost:5173` (proxies API requests to backend)
49+
50+
## Production Deployment (Docker)
51+
52+
### Pull from GitHub Container Registry
53+
54+
```bash
55+
# Pull the latest image
56+
docker pull ghcr.io/kengru/odin-wallet:latest
57+
58+
# Run with persistent data volume
59+
docker run -d \
60+
--name odin-wallet \
61+
-p 8080:8080 \
62+
-v $(pwd)/wallet-data:/app/data \
63+
-e SESSION_SECRET=your-secure-secret-here \
64+
ghcr.io/kengru/odin-wallet:latest
65+
```
66+
67+
Access the application at `http://localhost:8080`
68+
69+
### Build from Source
70+
71+
```bash
72+
# Build the Docker image
73+
docker build -t odin-wallet .
74+
75+
# Run the container
76+
docker run -d \
77+
--name odin-wallet \
78+
-p 8080:8080 \
79+
-v $(pwd)/wallet-data:/app/data \
80+
-e SESSION_SECRET=your-secure-secret-here \
81+
odin-wallet
82+
```
83+
84+
## Environment Variables
85+
86+
| Variable | Description | Default |
87+
| ---------------- | ------------------------------------------------------- | --------------------------------- |
88+
| `PORT` | Server port | `8080` |
89+
| `SESSION_SECRET` | Secret key for session cookies (required in production) | `dev-secret-change-in-production` |
90+
| `DB_PATH` | Path to SQLite database file | `./data/wallet.db` |
91+
92+
## Account Types
93+
94+
| Type | Description | Balance Field |
95+
| --------------- | -------------------------------- | ------------------------------------------ |
96+
| **Cash** | Physical cash tracking | `current_balance` |
97+
| **Debit Card** | Bank debit/checking accounts | `current_balance` |
98+
| **Credit Card** | Credit cards with limit tracking | `credit_owed` |
99+
| **Loan** | Loans with payment tracking | `loan_current_owed` |
100+
| **Savings** | Savings accounts with interest | `current_balance` + `yearly_interest_rate` |
101+
| **Investment** | Investment accounts | `current_balance` + `yearly_interest_rate` |
102+
103+
## Transaction Categories
104+
105+
Groceries, Dining, Transport, Utilities, Rent, Healthcare, Entertainment, Shopping, Subscriptions, Games, Travel, Education, Fitness, Personal, Gifts, Income, Transfer, Other
106+
107+
## API Endpoints
108+
109+
### Authentication
110+
111+
- `POST /api/auth/register` - Register a new user
112+
- `POST /api/auth/login` - Login
113+
- `POST /api/auth/logout` - Logout
114+
- `GET /api/auth/me` - Get current user
115+
116+
### Accounts
117+
118+
- `GET /api/accounts` - List all accounts
119+
- `POST /api/accounts` - Create account
120+
- `GET /api/accounts/:id` - Get account details
121+
- `PUT /api/accounts/:id` - Update account
122+
- `DELETE /api/accounts/:id` - Delete account
123+
- `GET /api/overview` - Get financial overview
124+
125+
### Transactions
126+
127+
- `POST /api/accounts/:id/transactions` - Create transaction
128+
- `GET /api/accounts/:id/transactions` - List account transactions
129+
- `GET /api/transactions/recent` - Get recent transactions across all accounts
130+
131+
## Project Structure
132+
133+
```
134+
wallet/
135+
├── cmd/server/ # Go server entry point
136+
├── internal/
137+
│ ├── handlers/ # HTTP request handlers
138+
│ ├── middleware/ # Auth middleware
139+
│ ├── models/ # Data models
140+
│ └── services/ # Business logic
141+
├── pkg/database/ # SQLite initialization
142+
├── frontend/
143+
│ ├── src/
144+
│ │ ├── api/ # API client
145+
│ │ ├── components/ # React components
146+
│ │ ├── contexts/ # React contexts
147+
│ │ ├── pages/ # Page components
148+
│ │ └── types/ # TypeScript types
149+
│ └── ...
150+
├── Dockerfile
151+
├── .github/workflows/ # CI/CD
152+
└── README.md
153+
```
154+
155+
## License
156+
157+
Private - Odin Company
158+
159+
---
160+
161+
Built with 💛 by Odin

0 commit comments

Comments
 (0)