100 lines
2.9 KiB
Markdown
100 lines
2.9 KiB
Markdown
# Fiscal Clone 3.0
|
|
|
|
Turbopack-first rebuild of a fiscal.ai-style terminal with OpenClaw integration.
|
|
|
|
## Stack
|
|
|
|
- Next.js 16 App Router
|
|
- Bun runtime/tooling
|
|
- Elysia route layer mounted in Next Route Handlers
|
|
- Turbopack for `dev` and `build`
|
|
- Better Auth (email/password, magic link, admin, organization plugins)
|
|
- Drizzle ORM (PostgreSQL) + Better Auth Drizzle adapter
|
|
- Internal API routes via Elysia catch-all (`app/api/[[...slugs]]/route.ts`)
|
|
- Durable local task engine and JSON data store
|
|
- OpenClaw/ZeroClaw analysis via OpenAI-compatible chat endpoint
|
|
|
|
## Run locally
|
|
|
|
```bash
|
|
bun install
|
|
bun run dev
|
|
```
|
|
|
|
Open [http://localhost:3000](http://localhost:3000).
|
|
|
|
Better Auth requires PostgreSQL. Set `DATABASE_URL`, `BETTER_AUTH_SECRET`, and `BETTER_AUTH_BASE_URL` in `.env.local`.
|
|
Generate and apply auth schema migrations before starting the app:
|
|
|
|
```bash
|
|
bun run db:generate
|
|
bun run db:migrate
|
|
```
|
|
|
|
## Production build
|
|
|
|
```bash
|
|
bun run db:migrate
|
|
bun run build
|
|
bun run start
|
|
```
|
|
|
|
## Docker deployment
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
docker compose up --build -d
|
|
```
|
|
|
|
For local Docker, host port mapping comes from `docker-compose.override.yml` (default `http://localhost:3000`, configurable via `APP_PORT`).
|
|
The base Docker Compose now includes an internal PostgreSQL service (`postgres`) used by Better Auth by default.
|
|
For Coolify/remote Docker Compose, only app container port `3000` is exposed internally (no fixed host port bind), avoiding host port collisions.
|
|
If you use an external Postgres instance, set `DATABASE_URL` explicitly.
|
|
Runtime data persists in the `app_data` volume (`/app/data` in container).
|
|
Docker images use Bun (`oven/bun:1.3.5-alpine`) for build and runtime.
|
|
|
|
## Environment
|
|
|
|
Use root `.env` or root `.env.local`:
|
|
|
|
```env
|
|
# leave blank for same-origin API
|
|
NEXT_PUBLIC_API_URL=
|
|
DATABASE_URL=postgres://postgres:postgres@localhost:5432/fiscal_clone
|
|
POSTGRES_DB=fiscal_clone
|
|
POSTGRES_USER=postgres
|
|
POSTGRES_PASSWORD=postgres
|
|
BETTER_AUTH_SECRET=replace-with-a-long-random-secret
|
|
BETTER_AUTH_BASE_URL=http://localhost:3000
|
|
BETTER_AUTH_ADMIN_USER_IDS=
|
|
BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:3000
|
|
|
|
OPENCLAW_BASE_URL=http://localhost:4000
|
|
OPENCLAW_API_KEY=your_key
|
|
OPENCLAW_MODEL=zeroclaw
|
|
SEC_USER_AGENT=Fiscal Clone <support@fiscal.local>
|
|
```
|
|
|
|
If OpenClaw is unset, the app uses local fallback analysis so task workflows still run.
|
|
|
|
## API surface
|
|
|
|
All endpoints below are handled by Elysia in `app/api/[[...slugs]]/route.ts`.
|
|
|
|
- `GET|POST|PATCH|PUT|DELETE /api/auth/*` (Better Auth handler)
|
|
- `GET /api/health`
|
|
- `GET /api/me`
|
|
- `GET|POST /api/watchlist`
|
|
- `DELETE /api/watchlist/:id`
|
|
- `GET|POST /api/portfolio/holdings`
|
|
- `PATCH|DELETE /api/portfolio/holdings/:id`
|
|
- `GET /api/portfolio/summary`
|
|
- `POST /api/portfolio/refresh-prices`
|
|
- `POST /api/portfolio/insights/generate`
|
|
- `GET /api/portfolio/insights/latest`
|
|
- `GET /api/filings`
|
|
- `POST /api/filings/sync`
|
|
- `POST /api/filings/:accessionNumber/analyze`
|
|
- `GET /api/tasks`
|
|
- `GET /api/tasks/:taskId`
|