Skip to content
Merged
189 changes: 189 additions & 0 deletions docs/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Jacare Developer Guide 🧑‍💻🐊

Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The important warning notice about Crocdb being offline is missing from this new documentation file. The original docs/README.md includes a critical notice at the top about the main Crocdb source being offline. This information should be included here for consistency and to inform users of current service status.

Suggested change
> Crocdb service status: The primary Crocdb metadata service is currently offline and not actively maintained. Features that depend on live requests to the Crocdb API (`https://api.crocdb.net`) may fail or behave differently from what is described in this document. Jacare still works for managing a local library and any previously cached metadata, but online lookups should be considered best-effort only.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the Crocdb offline warning notice to the nested developer guide. (4a98375)

> **⚠️ IMPORTANT NOTICE**: The main crocdb source is currently offline, causing data access failures. A root cause has been identified and a fix is in progress. An update will be published shortly with restored availability.

Welcome to the full technical README for **Jacare**, the Brazilian-inspired desktop ROM library manager that wraps the Crocdb API with an Electron + Express + React stack.

## Table of contents
- [Project overview](#project-overview)
- [Architecture](#architecture)
- [Repository layout](#repository-layout)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Development scripts](#development-scripts)
- [Configuration](#configuration)
- [Data & storage](#data--storage)
- [API reference](#api-reference)
- [Production build](#production-build)
- [Support](#support)

## Project overview
Jacare helps you browse, enrich, and launch ROMs from one place. It keeps your library on disk while pulling metadata from [Crocdb](https://crocdb.net) and reporting long-running work through jobs and SSE streams.

## Architecture
- **Electron shell** boots the server and ships the React UI for a native desktop experience.
- **Express API** powers Crocdb searches, manifest writing, and job orchestration.
- **React + Vite UI** calls the API over REST + SSE for real-time job updates.
- **SQLite backing store** keeps settings, cached Crocdb responses, library items, and job tracking tables.

## Repository layout
- `apps/server` – Express API, jobs, local scanning, and Crocdb client.
- `apps/web` – React UI (Vite) served by the server or opened directly in dev.
- `apps/desktop` – Electron main process that wraps the server and UI.
- `packages/shared` – Shared types, defaults, and the manifest schema used across workspaces.

## Prerequisites
- Node.js 20+
- npm
- Optional: Git LFS if you store binaries or media in the repo.

## Installation
```bash
npm ci
```

## Development scripts
- `npm run dev` – Run shared build watch + server + web + desktop together.
- `npm run dev:shared` – Start the shared package in watch mode.
- `npm run dev:server` – Start the Express API and job runners.
- `npm run dev:web` – Start the React UI via Vite.
- `npm run dev:desktop` – Start the Electron shell pointing at the dev server.
- `npm run build` – Build all workspaces.
- `npm run typecheck` – Type-check the monorepo.
- `npm run lint` – Lint all TypeScript and React code.
- `npm run test:unit` – Run unit tests with Vitest.

## Configuration
- `CROCDESK_PORT` (default `3333`) – Server port
- `CROCDESK_DATA_DIR` (default `./data`) – Directory for SQLite databases and cache
- `CROCDB_BASE_URL` (default `https://api.crocdb.net`) – Crocdb API base URL
- `CROCDB_CACHE_TTL_MS` (default `86400000`) – Cache TTL in milliseconds (24 hours)
- `CROCDESK_DEV_URL` (default `http://localhost:5173`) – Dev server URL for Electron

Settings stored in the database:
- `downloadDir` – Temporary directory for zip file downloads (deleted after extraction)
- `libraryDir` – Root directory where extracted game files are stored. All scanning and library operations work from this root.
- `queue.concurrency` (optional) – Maximum concurrent jobs

## Data & storage
- **SQLite tables:**
- `settings` – Application settings (downloadDir, libraryDir, queue config)
- `crocdb_cache_search` – Cached search results from Crocdb
- `crocdb_cache_entry` – Cached entry data from Crocdb
- `library_items` – Indexed ROM files with metadata
- `jobs` – Job records (scan_local, download_and_install)
- `job_steps` – Individual step progress for jobs
- **Manifests:** Each scanned ROM folder receives a `.crocdesk.json` manifest describing the game entry.
- **Data directory:** Defaults to `./data`; point it to a faster disk or network share as needed.

## API reference
- **Base URL:** `http://localhost:<CROCDESK_PORT>` (3333 by default) or the packaged server inside Electron.

### Crocdb endpoints
- `POST /crocdb/search` – Query Crocdb for matches. Request body: `{ search_key?, platforms?, regions?, rom_id?, max_results?, page? }`
- `POST /crocdb/entry` – Pull metadata and assets for a specific result. Request body: `{ slug }`
- `GET /crocdb/platforms` – Get available platforms
- `GET /crocdb/regions` – Get available regions
- `GET /crocdb/info` – Get Crocdb service info

### Library endpoints
- `GET /library/items?platform=<platform>` – List library items (optionally filtered by platform)
- `GET /library/games?platform=<platform>` – List library games (optionally filtered by platform)
- `POST /library/scan/local` – Trigger a local scan job
- `DELETE /library/item?dir=<path>` – Delete a library item and its directory

### Jobs endpoints
- `GET /jobs` – List all jobs with preview data
- `GET /jobs/:id` – Get job details and steps
- `POST /jobs/download` – Enqueue a download and install job. Request body: `{ slug, linkIndex? }`
- `POST /jobs/:id/cancel` – Cancel a job
- `POST /jobs/:id/pause` – Pause a job
- `POST /jobs/:id/resume` – Resume a paused job
- `POST /jobs/pause-all` – Pause all jobs
- `POST /jobs/resume-all` – Resume all paused jobs

### Settings endpoints
- `GET /settings` – Get current settings
- `PUT /settings` – Update settings. Request body: Settings object

### Other endpoints
- `GET /events` – SSE stream for job progress (scans, downloads, cache refreshes)
- `GET /file?path=<path>` – Serve files from the library directory (JSON files are parsed, others are streamed)
- `GET /health` – Health check endpoint
- `GET /api-config` – API configuration endpoint. Returns `{ apiUrl: string, port: number }` for frontend runtime configuration. The frontend uses this to auto-detect the correct API base URL.

**Responses:** Wrapped as `{ info, data }` objects for consistency.

## Production build

### Standalone Bundle (Recommended)

Create a single standalone binary that includes both the server and web UI:

```bash
npm run package:bundle
```

This will create binaries in `release/bundle/`:
- `jacare-win.exe` (Windows)
- `jacare-macos` (macOS)
- `jacare-linux` (Linux)

The bundle includes:
- Express server
- Web UI static assets
- All dependencies (including native modules)

No Node.js installation required—users can run the binary directly.

### Desktop App

Package the Electron app from `apps/desktop`:

```bash
npm run package:desktop
```

This bundles the server and web assets for a native desktop experience.

### Server Binary Only

Package just the server binary:

```bash
npm run package:server
```

### CI/CD

CI on `main` automatically publishes release archives with:
- Desktop app packages (Windows, macOS, Linux)
- Standalone bundle binaries
- Server-only binaries
- Latest changelog and README

## Troubleshooting

### Port and API URL Configuration Issues

**Problem**: Frontend shows CORS errors or can't connect to API, especially in Docker deployments.

**Solution**: The frontend uses runtime API URL detection. It will:
1. Check for `window.API_URL` (injected via script tag)
2. Fetch `/api-config` endpoint to auto-detect the API URL
3. Fall back to relative URLs for same-origin serving

**For Docker with custom port:**
- The `/api-config` endpoint automatically returns the correct API URL based on the request origin
- If frontend and backend are on different origins, inject `window.API_URL` in `index.html` via entrypoint script
- Never hardcode `localhost:3333` in frontend code

**Common issues:**
- **CORS errors**: Usually means frontend is trying to connect to wrong origin. Check that `/api-config` returns the correct URL.
- **Connection refused**: Frontend is using hardcoded `localhost:3333` instead of `getApiUrl()`. Always use `getApiUrl()` function.
- **Vite proxy not working**: Ensure `CROCDESK_PORT` environment variable is set when running `npm run dev:web`.

## Support
- Issues & roadmap: [GitHub Issues](https://github.com/luandev/jacare/issues)
- Crocdb service: [https://crocdb.net](https://crocdb.net) and [https://api.crocdb.net](https://api.crocdb.net)
- Tech stack docs: [Electron](https://www.electronjs.org/), [Express](https://expressjs.com/), [Vite](https://vitejs.dev/), [React](https://react.dev/)
124 changes: 124 additions & 0 deletions docs/docs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jacare Developer Guide</title>
<meta name="description" content="Technical documentation and developer guide for Jacare ROM library manager">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.5.1/github-markdown.min.css" integrity="sha384-OLBgp1GsljhM2TJ+sbHjaiH9txEUvgdDTAzHv2P24donTt6/529l+9Ua0vFImLlb" crossorigin="anonymous">
<style>
:root {
--bg: #0d1117;
--text: #c9d1d9;
--link: #58a6ff;
--border: #30363d;
}

@media (prefers-color-scheme: light) {
:root {
--bg: #ffffff;
--text: #24292f;
--link: #0969da;
--border: #d0d7de;
}
}

body {
margin: 0;
padding: 0;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
}

.header {
background: var(--bg);
border-bottom: 1px solid var(--border);
padding: 16px 24px;
position: sticky;
top: 0;
z-index: 100;
display: flex;
justify-content: space-between;
align-items: center;
}

.header-title {
font-size: 18px;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}

.header-links {
display: flex;
gap: 12px;
}

.header-links a {
color: var(--link);
text-decoration: none;
font-size: 14px;
}

.header-links a:hover {
text-decoration: underline;
}

.container {
max-width: 980px;
margin: 0 auto;
padding: 24px;
}

.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
}

@media (max-width: 767px) {
.container {
padding: 15px;
}
}
</style>
</head>
<body>
<div class="header">
<div class="header-title">
<span>🐊</span>
<span>Jacare Developer Guide</span>
</div>
<div class="header-links">
<a href="../../">Home</a>
<a href="../user/">User Guide</a>
<a href="https://github.com/luandev/jacare">GitHub</a>
</div>
</div>

<div class="container">
<article class="markdown-body" id="content">
<p>Loading documentation...</p>
</article>
</div>

<script src="https://cdn.jsdelivr.net/npm/marked@11.1.1/marked.min.js" integrity="sha384-aPoKub31DR9aRXyS6APWjc2IV99R+k/2y2HPv8P8X1wH4L3eZrFbEMlMxPYxzFLR" crossorigin="anonymous"></script>
<script>
async function loadMarkdown() {
try {
const response = await fetch('./README.md');
const markdown = await response.text();
const html = marked.parse(markdown);
document.getElementById('content').innerHTML = html;
} catch (error) {
document.getElementById('content').innerHTML = '<p>Error loading documentation. Please visit the <a href="https://github.com/luandev/jacare">GitHub repository</a> for the latest documentation.</p>';
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message display uses innerHTML to inject potentially unsafe content. While the current implementation only displays a hardcoded message, consider using textContent for the error path or sanitizing any dynamic content to prevent potential XSS issues if the error handling is modified in the future.

Suggested change
document.getElementById('content').innerHTML = '<p>Error loading documentation. Please visit the <a href="https://github.com/luandev/jacare">GitHub repository</a> for the latest documentation.</p>';
const contentEl = document.getElementById('content');
if (!contentEl) return;
// Clear any existing content
contentEl.textContent = '';
const paragraph = document.createElement('p');
paragraph.textContent = 'Error loading documentation. Please visit the ';
const link = document.createElement('a');
link.href = 'https://github.com/luandev/jacare';
link.textContent = 'GitHub repository';
paragraph.appendChild(link);
paragraph.appendChild(document.createTextNode(' for the latest documentation.'));
contentEl.appendChild(paragraph);

Copilot uses AI. Check for mistakes.
}
}

loadMarkdown();
</script>
</body>
</html>
68 changes: 68 additions & 0 deletions docs/docs/user/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Jacare Friendly Guide 😀🐊

Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The important warning notice about Crocdb being offline is missing from this new documentation file. The original docs/user/README.md includes a critical notice at the top about the main Crocdb source being offline. This information should be included here for consistency and to inform users of current service status.

Suggested change
> **Important:** The main Crocdb metadata service is currently offline/unavailable.
> Jacare will still work for managing your local ROM library, but features that depend on Crocdb (online search, metadata enrichment, and downloads) may be limited or fail until the service is restored.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the Crocdb offline warning notice to the nested user guide. (4a98375)

> **⚠️ IMPORTANT NOTICE**: The main crocdb source is currently offline, causing data access failures. A root cause has been identified and a fix is in progress. An update will be published shortly with restored availability.

This guide is for anyone who wants to use Jacare without digging into code. Follow the steps below to organize your ROM collection with minimal setup.

## What is Jacare?
Jacare is a desktop app that helps you keep your game ROMs tidy. It finds details like cover art and descriptions using the Crocdb online database while storing your library on your computer.

## Quick start
1. **Install the app**

**Option A: Docker (Recommended)**
- Install [Docker Desktop](https://www.docker.com/products/docker-desktop) (Windows/macOS) or Docker Engine (Linux)
- Download the [`docker-compose.yml`](https://github.com/luandev/jacare/blob/main/docker/docker-compose.yml) file
- Adjust bind mounts to match your host paths (see [Docker README](https://github.com/luandev/jacare/blob/main/docker/README.md) for details)
- Start Jacare:
```bash
docker compose up -d
```
- For Linux/macOS users, ensure proper permissions: `sudo chown -R 1001:1001 /path/to/data`

**Option B: Standalone Bundle (No Node.js required)**
- Download the standalone binary for your system from the [releases page](https://github.com/luandev/jacare/releases):
- Windows: `jacare-win.exe`
- macOS: `jacare-macos` (make executable with `chmod +x jacare-macos`)
- Linux: `jacare-linux` (make executable with `chmod +x jacare-linux`)
- Run the binary directly—no installation needed!

**Option C: Desktop App**
- Download the Jacare desktop package for your system (Windows/macOS/Linux) from the [releases page](https://github.com/luandev/jacare/releases).
- Install it like any other app.

2. **Open Jacare**
- **Docker:** Open your browser and go to `http://localhost:3333`
- **Standalone bundle:** Run the binary. The server and web UI start automatically, then open `http://localhost:3333`
- **Desktop app:** Launch the app. The server and the visual interface start automatically.
3. **Configure your library**
- Go to **Settings** and set your **Library Directory** to the folder containing your ROM files.
- Optionally set a **Download Directory** for temporary downloads (files are deleted after extraction).
4. **Let Jacare scan**
- Go to the **Library** page and click **Scan** to let Jacare discover the ROMs in your library directory. Progress appears in the app.
5. **Search for game details**
- Use **Browse** to search for matches from Crocdb. When you like a result, pick **Download** to pull the ROM and enrich your library with cover art and metadata.
6. **Launch and enjoy**
- Launch games directly from Jacare, or open the manifest to plug it into another launcher.

## Staying organized
- Keep your ROMs in clearly named folders organized by platform (e.g., `library/snes/`, `library/n64/`).
- Re-run **Scan** after adding new games so Jacare can index them.
- If you're offline, you can still browse what was already scanned, and Jacare will use cached results until you reconnect.
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement is inaccurate. According to the project's coding guidelines, downloads are disabled by default for safety and require setting CROCDESK_ENABLE_DOWNLOADS=true to enable. The text should be corrected to: "Downloads are disabled by default. Enable them with CROCDESK_ENABLE_DOWNLOADS=true environment variable."

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! Downloads are now correctly documented as disabled by default, with CROCDESK_ENABLE_DOWNLOADS=true required to enable them. (4a98375)


## Settings explained
- **Library Directory:** This is where your ROM files are stored. Jacare scans this directory recursively to find games. All library operations work from this root.
- **Download Directory:** Temporary directory for zip file downloads. Files are automatically deleted after extraction to your library directory.
- **Theme:** Choose between light and dark themes for the interface.

## Common questions
- **Do I need an account?** No—Jacare uses Crocdb without sign-in.
- **Where does it store data?** In a `data` folder next to the app (or in the location specified by `CROCDESK_DATA_DIR`), including SQLite databases and small `.crocdesk.json` manifest files in each ROM folder.
- **Can I turn off downloads?** Downloads are disabled by default for safety. Enable them by setting the `CROCDESK_ENABLE_DOWNLOADS=true` environment variable.
- **Is my collection safe?** Jacare reads your ROMs and metadata but keeps everything on your device unless you choose to share it.
- **What file formats are supported?** Jacare supports common ROM formats including `.zip`, `.7z`, `.rar`, `.iso`, `.chd`, `.bin`, `.cue`, `.sfc`, `.smc`, `.nes`, `.gba`, `.gb`, `.gbc`, `.n64`, `.z64`, `.v64`, `.nds`, `.md`, `.gen`, `.sms`, `.gg`, `.pce`, `.img`, `.ccd`, `.sub`, `.m3u`, and more.

## Need help?
- Check for updates on the [GitHub releases page](https://github.com/luandev/jacare/releases).
- Open an issue on [GitHub](https://github.com/luandev/jacare/issues) with details about what went wrong and what you expected.
- Planning to load ROMs onto a retro handheld like the R36S or RG40XXH? See the handheld-specific walkthrough in [`retro-handhelds.md`](./retro-handhelds.md).
Loading
Loading