UI: warm daylight design system (Tailwind v4 @theme palette, gh-* component classes, watercolor grain, Zen Maru Gothic + Klee One fonts), animated SSR-safe GhibliBackground (drifting clouds, meadow hills, soot sprites), and a full reskin of navbar, connect button, dapp page, loan cards, settings modal, and readme. Fixes the bg-white-on-dark loan-card inconsistency. Web3/business logic untouched. Docs: converted docs/ into an Obsidian vault (frontmatter, [[wikilinks]], callouts, Home MOC, folders Architecture/Operations/Audits) and added a full-project audit note (Project Audit 2026-06). Redacted a real leaked Schedy key value from the security audit example (rotate it at Schedy). Also commits the previously-untracked server layer: app/api (cron + tasks routes) and lib (redis, ssrf-guard, task-store). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.1 KiB
title, tags, type, status, updated
| title | tags | type | status | updated | |||
|---|---|---|---|---|---|---|---|
| Development |
|
operations | stable | 2026-06-14 |
Development
Repository Structure
mortgageFi/
├── mortgagefi-frontend/ # Next.js DApp
│ ├── app/ # App Router pages
│ │ ├── dapp/page.tsx # Main DApp interface
│ │ ├── dapp/position/... # Deep-link position pages
│ │ ├── layout.tsx # Root layout with Web3Provider
│ │ └── page.tsx # Landing page
│ ├── components/ # React components
│ │ ├── ConnectButton.tsx
│ │ ├── Navbar.tsx
│ │ └── SettingsModal.tsx # Notification settings
│ ├── providers/
│ │ └── Web3Provider.tsx # Wagmi + QueryClient setup
│ ├── utils/
│ │ ├── scheduler.ts # Schedy API client
│ │ ├── useLocalStorage.ts # localStorage hook
│ │ ├── format.ts # Number formatting
│ │ └── cronhost.ts # Legacy cronhost support
│ ├── config/
│ │ └── web3.ts # Wagmi chain config
│ ├── types/
│ │ └── notifications.ts # TypeScript types
│ ├── ABIs/
│ │ └── mortgagefiusdccbbtcupgraded.json
│ └── submodules/
│ └── schedy/ # Go scheduler (Git submodule)
├── nftcache/ # Go NFT ownership cache
│ ├── cmd/nftcache/main.go
│ └── internal/
│ ├── config/config.go # YAML contract config
│ ├── fetcher/
│ │ ├── rpc.go # RPC scanning with rate limits
│ │ └── alchemy.go # Alchemy API fallback
│ └── store/store.go # BadgerDB persistence
├── config/
│ └── contracts.yaml # Contract address mappings
├── nginx/
│ └── nginx.conf # Reverse proxy config
├── docker-compose.yml # Full stack orchestration
├── .env / .env.local # Environment variables
├── ALERT_CHANGES.md # Alert feature changelog
└── MIGRATION_NOTES.md # Dependency upgrade notes
Frontend Development
Setup
cd mortgagefi-frontend
npm install
Run Dev Server
npm run dev
# Opens on http://localhost:3000
[!info] Turbopack is enabled by default for faster builds.
Build for Production
npm run build
npm start
Lint
npm run lint
Environment Variables
Create mortgagefi-frontend/.env.local:
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your-project-id
NEXT_PUBLIC_RPC_BASE=https://base.llamarpc.com
Note
See
.envin the repo root for the full variable list.
Backend Development
nftcache
cd nftcache
# Run
go run ./cmd/nftcache
# Build
go build -o nftcache ./cmd/nftcache
./nftcache
# With custom env
NFTCACHE_API_KEY=test NFTCACHE_TTL=1h go run ./cmd/nftcache
Test the API:
# After starting, test with:
curl "http://localhost:8090/nfts?network=base&nft_contract=cbbtc&user_wallet=0x..."
schedy
cd mortgagefi-frontend/submodules/schedy
# Run
go run ./cmd/schedy
# Build
go build -o schedy ./cmd/schedy
./schedy -port 8080
Test the API:
# Create a task
curl -X POST http://localhost:8080/tasks \
-H "Content-Type: application/json" \
-H "X-API-Key: test" \
-d '{
"url": "https://httpbin.org/post",
"execute_at": "2026-12-31T23:59:59Z",
"payload": "test"
}'
# List tasks
curl http://localhost:8080/tasks -H "X-API-Key: test"
Full Stack Local Development
Run all services together with Docker Compose:
# From repo root
docker compose up -d
# Watch logs
docker compose logs -f
# Restart a single service
docker compose restart frontend
docker compose restart nftcache
# Rebuild after code changes
docker compose up -d --build frontend
docker compose up -d --build nftcache
The nginx proxy exposes everything on http://localhost:
/— Next.js frontend/ntfy/— ntfy web UI and API/schedy/— Schedy API/nftcache/— nftcache API
Adding a New Chain/Preset
1. Update Frontend (mortgagefi-frontend/app/dapp/page.tsx)
Add chain defaults:
const DEFAULTS = {
[base.id]: { nft: '0x...', debt: '0x...' },
[arbitrum.id]: { nft: '0x...', debt: '0x...' },
[newChain.id]: { nft: '0x...', debt: '0x...' },
};
Add presets:
const PRESETS = {
[newChain.id]: [
{ key: 'PAIR-QUOTE', label: 'PAIR-QUOTE', nft: '0x...', debt: '0x...' },
],
};
2. Update Web3 Config (mortgagefi-frontend/config/web3.ts)
import { newChain } from 'wagmi/chains';
export const config = createConfig({
chains: [base, arbitrum, newChain],
transports: {
[newChain.id]: http('https://newchain.rpc.com'),
},
});
3. Update nftcache (config/contracts.yaml)
contracts:
mypreset:
network: newchain
address: "0x..."
max_token_id: "10000"
4. Add RPC to nftcache environment
NEWCHAIN_RPC_URL=https://newchain.rpc.com
Update nftcache/cmd/nftcache/main.go to read the new env var.
Testing Notifications End-to-End
1. Configure Settings in UI
Open the DApp, click Settings (gear icon):
- Provider: ntfy
- Server:
/ntfy(or your ntfy URL) - Topic:
mortgagefi-test - Email: your email address
- Scheduler: Schedy
- Schedy URL:
/schedy - Schedy API Key: your key
2. Send Test Alert
Click "Send test alert" in Settings.
3. Verify
Check:
- ntfy web UI at
http://localhost/ntfy/— message should appear - Your email inbox — message should arrive within seconds (or 2 minutes for Schedy tests)
4. Manual Test via cURL
# Direct ntfy test
curl -X POST http://localhost/ntfy/mortgagefi-test \
-H "Content-Type: text/plain" \
-H "X-Email: you@example.com" \
-d "Manual test"
# Schedy + ntfy test
curl -X POST http://localhost/schedy/tasks \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key" \
-d '{
"url": "http://localhost/ntfy/mortgagefi-test",
"headers": {"Content-Type":"text/plain","X-Email":"you@example.com"},
"payload": "Scheduled test",
"execute_at": "'$(date -u -v+2M +%Y-%m-%dT%H:%M:%SZ)'"
}'
Common Issues
429 Rate Limit Errors
[!warning] RPC returns "Too Many Requests" during NFT scanning.
Solutions:
- Use a private RPC endpoint (Infura, Alchemy, QuickNode)
- Reduce
NFTCACHE_TTLto reduce background refresh frequency - Enable nftcache in frontend settings to offload scanning
Wallet Connection Fails
[!warning] WalletConnect modal doesn't appear.
Solutions:
- Verify
NEXT_PUBLIC_WALLETCONNECT_PROJECT_IDis set - Check that the project ID is valid at https://cloud.walletconnect.com
Schedy Tasks Not Executing
[!warning] Scheduled alerts never fire.
Debugging:
# List pending tasks
curl http://localhost/schedy/tasks -H "X-API-Key: your-key"
# Check schedy logs
docker compose logs -f schedy
Common causes:
- Schedy container clock drift (ensure NTP is enabled)
- Task deleted before execution (check auto-reschedule logic)
- ntfy URL unreachable from Schedy container
CORS Errors
[!warning] Browser blocks API calls to Schedy or nftcache.
Solution:
Ensure CORS_ALLOW_ORIGIN matches your frontend URL exactly, including protocol:
CORS_ALLOW_ORIGIN=https://mortgagefi.example.com
Git Submodules
The schedy project is included as a Git submodule:
# Initialize on fresh clone
git submodule update --init --recursive
# Pull latest submodule changes
git submodule update --remote
# Commit submodule pin
cd mortgagefi-frontend/submodules/schedy
git checkout main
git pull
cd ../../..
git add mortgagefi-frontend/submodules/schedy
git commit -m "Update schedy submodule"