From a8321ea498015b562cc3f353e9112b335d6aa668 Mon Sep 17 00:00:00 2001 From: Evandro Fonseca Junior Date: Sat, 24 Oct 2026 04:54:38 -0300 Subject: [PATCH] docs(readme): redesenha o README com hero em SVG [skip ci] --- README.md | 161 +++++++++++------------------------------ assets/readme/hero.svg | 46 ++++++++++++ 2 files changed, 89 insertions(+), 118 deletions(-) create mode 100644 assets/readme/hero.svg diff --git a/README.md b/README.md index 6917817..6a40f48 100644 --- a/README.md +++ b/README.md @@ -1,158 +1,83 @@
-

LocalMind

+LocalMind: chat with your LM Studio models from a phone or browser on your own network -

Chat client for local LLMs served by LM Studio, on Android, iOS and web. Every message stays on your network: no cloud.

+![React Native 0.81](https://img.shields.io/badge/React_Native-0.81-61DAFB?style=flat-square&logo=react&logoColor=black) +![Expo 54](https://img.shields.io/badge/Expo-54-1C1E24?style=flat-square&logo=expo&logoColor=white) +![TypeScript 5.9](https://img.shields.io/badge/TypeScript-5.9-3178C6?style=flat-square&logo=typescript&logoColor=white) +![Platforms](https://img.shields.io/badge/platforms-Android_%7C_iOS_%7C_Web-555?style=flat-square) +![Status](https://img.shields.io/badge/status-alpha-orange?style=flat-square) -Quickstart · -Architecture · -Issues - -![Stack](https://img.shields.io/badge/Stack-React_Native_0.81_%2B_Expo_54-1C1E24?logo=expo&logoColor=white) -![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript&logoColor=white) -![Status](https://img.shields.io/badge/status-alpha-orange) -![License](https://img.shields.io/badge/license-none_defined-lightgrey) +[Quick start](#quick-start) · [Issues](https://git.evandro.dev.br/evandro/LocalMind/issues)
-
+## What it is -## 📌 The problem +LocalMind is a chat client for the models you run in [LM Studio](https://lmstudio.ai). It is an Expo app for Android, iOS and the web that talks to LM Studio's OpenAI-compatible `/v1` API over your LAN or `localhost`. It is only the client: there is no backend, no account and no server to deploy. -Running a model locally in LM Studio is easy; having a decent chat UI for it on your phone is not. Hosted chat apps send every message to a cloud service, which defeats the point of running the model yourself. +## Why use it -LocalMind is only the client. There is no backend, no account and no server to deploy: the model runs on your machine and the app talks to it over your LAN or `localhost`. +- **Your messages stay on your network.** The app only talks to the LM Studio address you set in Settings. There is no cloud API and no fallback to one. +- **Real streaming on every target.** Requests go out with `stream: true` and each SSE `choices[0].delta.content` is appended as it arrives: through `XMLHttpRequest` progress events on native, through `fetch` with a `ReadableStream` on the web. You can stop generation mid-stream. +- **The chat basics are there.** Markdown with copyable code blocks, edit, delete and regenerate, a model selector fed by LM Studio, history saved on the device, and light, dark or system theme. -## ✨ What it does +**When not to use it:** if you want a cloud model, a server other than LM Studio (the app was built against LM Studio only), or a verified phone build. The Android and iOS builds and the native streaming path have not been verified yet. -- Connects to the LM Studio local server through its OpenAI-compatible `/v1` API. -- Streams answers token by token and lets you stop generation while it streams. -- Renders Markdown with code blocks, with a copy button for code. -- Edits, deletes and regenerates messages in the conversation. -- Lists the models loaded in LM Studio in a header selector. -- Saves every finished exchange as a chat session on the device; History reloads or deletes it. -- Tests the server connection from Settings and shows a Connected / Disconnected badge. -- Switches between light, dark and system themes. +## How it works -## 🚀 Quickstart +- Screens are file-based routes (`expo-router`): `app/chat`, `app/chat/history` and `app/settings`. `hooks/useLMStudio` exposes send, regenerate, stop and model fetching. +- `services/lmStudioApi` builds `http(s)://:/v1`, calls `GET /v1/models` for the selector and the connection test, and streams `POST /v1/chat/completions`. +- `store/useAppStore` (Zustand) persists theme, server settings, chat sessions and the current chat in `AsyncStorage`. A finished exchange becomes a session titled from the first user message. -| Tool | Minimum version | -|---|---| -| Node.js | `>= 20.19.4` (required by React Native 0.81.5; not declared in `package.json`) | -| npm | any recent version (`package-lock.json` is committed; `pnpm-lock.yaml` too) | -| [LM Studio](https://lmstudio.ai) | with at least one model downloaded; local server on port `1234` by default | -| Run target | [Expo Go](https://expo.dev/go) on a device, an Android/iOS emulator, or a browser | +## Quick start -### 1. Start the model server (LM Studio) +You need Node.js 20.19.4 or newer (required by React Native 0.81; not declared in `package.json`), npm, and LM Studio with at least one model downloaded. To run the app, use [Expo Go](https://expo.dev/go) on a device, an Android or iOS emulator, or a browser. -1. Open LM Studio, download a model and go to the **Local Server** tab (the `<->` icon). -2. Load the model, enable **CORS** and keep the port at `1234` (or note the one you choose). -3. Click **Start Server**. +**1. Start LM Studio's server.** Open the **Local Server** tab (the `<->` icon), load a model, enable **CORS**, keep the port at `1234` (or note yours) and click **Start Server**. -### 2. Run the app +**2. Run the app.** ```bash git clone https://git.evandro.dev.br/evandro/LocalMind.git cd LocalMind npm install -npm run start # Expo CLI: press w (web), a (Android), i (iOS) or scan the QR with Expo Go -# or go straight to a target: -npm run android -npm run ios -npm run web +npm run start # Expo CLI: press w (web), a (Android), i (iOS) or scan the QR code with Expo Go ``` -### 3. Point the app at LM Studio +`npm run android`, `npm run ios` and `npm run web` open a target directly. Do not run `npm run reset-project`: it is the Expo template script and moves or deletes `app/`, `components/`, `hooks/`, `constants/` and `scripts/`. -1. Open **Settings** (gear icon in the chat header). -2. Fill **Host IP / Address** and **Port Number**. On a physical device the host must be your machine's LAN address (`192.168.x.x`), not `localhost`. -3. Tap **Test Connection**. The badge turns to *Connected* and the loaded models appear in the header selector. +**3. Point the app at LM Studio.** Open **Settings** (gear icon in the chat header), fill **Host IP / Address** and **Port Number**, then tap **Test Connection**. On a physical device the host must be your computer's LAN address (`192.168.x.x`), not `localhost`. The badge turns to *Connected* and the loaded models appear in the header. Until then the chat shows *Server offline*: the app does not connect on launch. -Until you do this the chat shows *Server offline*: the app does not connect on launch. +## Configuration -### Network configuration +The app reads no environment variables. The server address is a runtime setting stored on the device: -The app has no `.env.example` and reads no environment variables. The server address is a runtime setting stored on the device. - -| Setting | Required | Description | +| Setting | Default | Notes | |---|---|---| -| Host IP / Address | Yes | Default `localhost` (`DEFAULT_SERVER_CONFIG` in `services/types.ts`). `http://` is prepended when the value does not start with `http`. | -| Port Number | Yes | Default `1234`, the LM Studio default. | -| API Key (optional) | No | Empty by default. Sent as `Authorization: Bearer ` only when filled in. | +| Host IP / Address | `localhost` | `http://` is prepended when the value does not start with `http` | +| Port Number | `1234` | LM Studio's default port | +| API Key (optional) | empty | Sent as `Authorization: Bearer ` only when filled in | -The resulting base URL is `http(s)://:/v1`. Defaults for a local LM Studio: `http://localhost:1234/v1`. +Everything else lives in code: `temperature: 0.7` and `max_tokens: 2048` in `services/lmStudioApi.ts` (the connection test gives up after 5 s), the fixed system prompt in `constants/SystemPrompt.ts`, and the persisted state under the `localaiapp-storage` key in `store/useAppStore.ts`. -Other configuration lives in code, not in the UI: +## Project status -| Where | What | -|---|---| -| `services/lmStudioApi.ts` | `temperature: 0.7`, `max_tokens: 2048`; the connection test aborts after 5 s | -| `constants/SystemPrompt.ts` | Fixed system prompt sent with every request | -| `app.json` | App name `LocalAiApp`, scheme `localaiapp`, `newArchEnabled`, `web.output: static`, `typedRoutes` and `reactCompiler` experiments | -| `store/useAppStore.ts` | Persisted under the `localaiapp-storage` key: theme, server config, chat sessions, current messages | +Alpha, with no tests and no CI. Known gaps: -## 🧱 Architecture - -```mermaid -flowchart LR - Screens["Screens: app/chat, app/settings"] --> Hook["hooks/useLMStudio"] - Hook --> Api["services/lmStudioApi"] - Hook --> Store["store/useAppStore"] - Store --> Storage[("AsyncStorage")] - Api -->|"GET /v1/models, POST /v1/chat/completions"| LM["LM Studio local server"] -``` - -- Screens are file-based routes (`expo-router`). `useLMStudio` exposes send, regenerate, stop and model fetching. -- `lmStudioApi` builds the base URL and streams the response: `XMLHttpRequest` progress events on native, `fetch` with `ReadableStream` on web. -- Streaming uses `stream: true`; SSE lines with `choices[0].delta.content` are appended to the last message. -- `GET /v1/models` feeds the model selector and the connection test. -- The Zustand store is persisted with `AsyncStorage`; a finished exchange becomes a session titled from the first user message. - -## 🗂️ Structure - -``` -app/ expo-router screens: chat/, chat/history, settings/, +not-found -components/ chat/ (ChatInput, MessageBubble, ModelSelector...) and ui/ -constants/ Colors, theme, SystemPrompt, Models (unused) -hooks/ useLMStudio, useThemeColor, useColorScheme -services/ lmStudioApi (HTTP + SSE), types (ServerConfig, defaults) -store/ useAppStore (Zustand + AsyncStorage) -docs/ LM Studio API notes, design system reference -.agent/ AI development tooling, not app code -``` - -## 🧪 Scripts - -| Command | What it does | -|---|---| -| `npm run start` | `expo start`: Expo dev server, pick a target from the CLI | -| `npm run android` | `expo start --android` | -| `npm run ios` | `expo start --ios` | -| `npm run web` | `expo start --web` | -| `npm run lint` | `expo lint` (ESLint 9 flat config, `eslint-config-expo`) | -| `npm run reset-project` | `node ./scripts/reset-project.js`: Expo template script that moves or deletes `app/`, `components/`, `hooks/`, `constants/` and `scripts/`. **Do not run it on this project.** | - -Not scripts, but used by this project: `npx tsc --noEmit` (strict TypeScript check) and `npx expo export --platform web` (static build into `dist/`; serve it with a static server that resolves extension-less URLs, such as `npx serve dist`). - -## 📚 Documentation - -- [`docs/Documentação de Implementaçoes Futuras.md`](docs/Documenta%C3%A7%C3%A3o%20de%20Implementa%C3%A7oes%20Futuras.md): notes on the LM Studio API (`/api/v0`, `/v1`, SDKs, CLI) and ideas, in Portuguese. -- [`docs/evandro-design-system.html`](docs/evandro-design-system.html): visual reference of the design system used in the UI. - -## 🛣️ Limitations and next steps - -- Alpha. Built against models served by LM Studio; no fallback to any cloud API. -- No auto-connect on launch: the server is only checked from Settings or when the model selector refreshes. -- `activeModelId` and `availableModels` are not persisted, so you select a model again after a restart. +- The selected model and the model list are not persisted, so you pick a model again after a restart. - `constants/Models.ts` (a Qwen model catalog) and the `react-native-sse` dependency are not used by any code. - `app.json` and the storage key still carry the previous project name (`LocalAiApp`, `localaiapp-storage`). - Both `package-lock.json` and `pnpm-lock.yaml` are committed. -- No tests and no CI. The previous README reported `npx tsc --noEmit` clean and `npx expo lint` with 0 errors and 3 warnings; Android and iOS builds, and the native `XMLHttpRequest` streaming path, were never verified. -## 🤝 Contributing +Before opening a PR, run `npm run lint` (Expo's ESLint config) and `npx tsc --noEmit`. Notes on the LM Studio API, in Portuguese, are in [`docs/`](docs/). -There is no test suite. Before opening a PR, make sure `npm run lint` and `npx tsc --noEmit` pass, and open issues on the [issue tracker](https://git.evandro.dev.br/evandro/LocalMind/issues). +## License -## 📄 License +No published license: all rights reserved. -No license defined — all rights reserved. + diff --git a/assets/readme/hero.svg b/assets/readme/hero.svg new file mode 100644 index 0000000..46728db --- /dev/null +++ b/assets/readme/hero.svg @@ -0,0 +1,46 @@ + + LocalMind + LocalMind: a phone chat screen marked Connected talks over the local network to LM Studio running on your computer at port 1234, path /v1. + + + + + LocalMind + Chat with your LM Studio models + from a phone or browser on your LAN. + React Native 0.81 · Expo 54 · TypeScript + + + + + + + + Connected + + Explain SSE + + + + + + + Message + + + + + + + LAN + + + + + LM Studio + :1234/v1 + + + your machine + +