Formatlane is a privacy-first browser toolkit for developers working with structured text, API payloads, snippets, and credentials. Most tools run entirely in the browser, while the optional backend provides account login, cloud snippet sync, and encrypted secret storage.
- JSON formatter, validator, path extractor, JSON Schema checker, CSV converter, YAML converter, and TypeScript interface generator.
- YAML formatter, validator, path extractor, and JSON converter for common configuration-style YAML.
- Text utilities for search, replace, casing, Base64, ROT13, word counts, and line/column inspection.
- HTML formatter, sandboxed preview, entity encode/decode, XML-style validation, and basic accessibility checks.
- SQL formatter, heuristic validator, dialect hints, table/parameter extraction, and SQL command cheatsheet.
- XML validator, formatter, XPath runner, XSLT transformer, and implemented-subset XSD checker.
- JWT decoder, registered claim inspector, timestamp checks, HS256 verification, and JWKS verification for common RSA/ECDSA algorithms.
- Markdown previewer with tables, task lists, footnotes, generated table of contents, HTML export, and word count.
- CSV formatter, delimiter switcher, row-length validator, table preview, and CSV-to-JSON conversion.
- Regex tester with JavaScript execution, capture group inspection, engine compatibility notes, pattern library, and copyable snippets for several languages.
- Diff checker with content type detection, structured formatting, line diff, character diff, and JSON structural diff.
- Account workspace for local/cloud/mixed snippet storage, encrypted snippet passphrases, ZIP import/export, and account profile updates.
The project is split into a React frontend and a FastAPI backend.
src/
App.jsx App shell, routing, auth session checks
tools/ Workspace UI components
utils/ Parsers, validators, formatters, encryption helpers
hooks/useLocalStorageState.js
services/backendClient.js Cookie-based API client
backend/
app/main.py FastAPI routes
app/security.py Argon2 password hashing and JWT helpers
app/models.py SQLAlchemy models
app/schemas.py Pydantic request/response schemas
docs/
deployment/README.md Production deployment details
project-implementation-hu.md
Frontend state is stored in localStorage per workspace. Snippet encryption passphrases are stored only in sessionStorage, so users need to re-enter them in a new browser session.
- Frontend: React 19, Vite 7, JavaScript ES modules.
- Backend: FastAPI, SQLAlchemy, Uvicorn, Pydantic.
- Auth: HTTP-only cookie containing an HS256 JWT.
- Password hashing: Argon2 via
passlib. - Client-side encryption: WebCrypto AES-GCM with PBKDF2-SHA256.
- Database: SQLite by default, configurable with
DATABASE_URL. - Production deployment: GitHub Actions, nginx, Docker, certbot.
- Node.js 22 or compatible modern Node version.
- npm.
- Python 3.12.
- Docker, optional but recommended for running the backend like production.
npm install
python3 -m pip install -r backend/requirements.txtnpm run devThe Vite dev server normally runs at:
http://localhost:5173
docker compose up --buildThe backend is exposed locally at:
http://localhost:8001
Health check:
curl http://localhost:8001/healthExpected response:
{"status":"ok"}DATABASE_URL=sqlite:///./tool_site.db \
JWT_SECRET=dev-only-change-me \
COOKIE_SECURE=false \
CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 \
uvicorn backend.app.main:app --reload --host 0.0.0.0 --port 8001If the frontend should call a different backend URL, set:
VITE_API_BASE_URL=http://localhost:8001 npm run devnpm run dev # start Vite
npm run build # build frontend into dist/
npm run preview # preview production frontend build
npm test # run frontend utility tests and backend API testsThe test command runs:
node --testpython3 -m unittest discover backend/tests
Frontend:
| Variable | Default | Purpose |
|---|---|---|
VITE_API_BASE_URL |
http://localhost:8001 |
Backend API base URL used by the browser client. |
Backend:
| Variable | Default | Purpose |
|---|---|---|
DATABASE_URL |
sqlite:///./tool_site.db |
SQLAlchemy database URL. |
JWT_SECRET |
dev-only-change-me |
HS256 JWT signing secret. Must be changed in production. |
COOKIE_SECURE |
false |
Set to true behind HTTPS in production. |
CORS_ORIGINS |
localhost Vite origins | Comma-separated allowed browser origins. |
Main endpoints:
GET /healthPOST /auth/registerPOST /auth/loginPOST /auth/logoutGET /mePATCH /me/emailPATCH /me/passwordGET /snippetsPOST /snippetsPATCH /snippets/{snippet_id}DELETE /snippetsDELETE /snippets/{snippet_id}GET /secretsPOST /secretsGET /exportDELETE /me
Authentication is cookie-based. Login and register set an HTTP-only formatlane_access_token cookie. The frontend tracks only whether a cookie-backed session appears valid; it does not read or store the JWT.
Formatlane is local-first by design.
- Workspace input is stored in the browser's
localStorage. - Local snippets are stored in browser
localStorage. - Cloud snippets are stored through the backend only when the user is logged in and chooses cloud or mixed storage.
- Snippet passphrases are session-only and are not uploaded.
- Encrypted snippets and API secrets use AES-GCM in the browser before storage.
- Cloud encrypted snippets and secrets upload ciphertext, salt, IV, and metadata only.
Encryption details:
- KDF: PBKDF2-SHA256.
- Iterations: 250,000.
- Salt: 16 random bytes.
- IV: 12 random bytes.
- Cipher: AES-GCM with a 256-bit key.
Changing a passphrase does not re-encrypt existing snippets. Older encrypted snippets still require the passphrase used when they were saved. If that passphrase is lost, the app cannot recover the content.
ZIP export can contain plaintext snippets if the current passphrase can decrypt them during export.
Several tools intentionally use lightweight built-in parsers or project-local parsers to keep the app small and browser-first.
- JSON uses native
JSON.parseplus extra heuristic error messages. - YAML is a custom subset parser for common config-style documents, not a full YAML 1.2 implementation.
- Markdown is a custom renderer, not a full CommonMark implementation.
- SQL formatting and validation are regex/heuristic based and do not replace a real database parser.
- HTML formatting is token-based and XML-style validation is stricter than real browser HTML parsing.
- CSV parsing supports common quoted fields, escaped quotes, CRLF/LF rows, multiline fields, and delimiters, but is not a full spreadsheet compatibility layer.
- Curl import supports common request-building options, not every curl flag.
Use the built-in validators as fast developer feedback. For production-critical validation, verify with the official parser/runtime for the target format, database, or platform.
Production deployment is automated with GitHub Actions in:
.github/workflows/deploy.yml
The deployment model:
- Frontend is built by Vite and uploaded to
/var/www/tool-site/current. - Backend source is uploaded to
/opt/tool-site/backend. - Backend runs in Docker on
127.0.0.1:8001. - nginx serves the frontend and reverse-proxies
/api/to the backend. - certbot issues TLS certificates for the configured domain.
- SQLite data is stored in a Docker named volume and is not synced from CI.
Required GitHub Actions secrets:
| Secret | Purpose |
|---|---|
DEPLOY_HOST |
Server IP address or hostname. |
DEPLOY_USER |
Linux deploy user. |
DEPLOY_DOMAIN |
Public domain for nginx and TLS. |
DEPLOY_ROOT_PASSWORD |
Root SSH password for first bootstrap. |
DEPLOY_SSH_PRIVATE_KEY |
Private key used by Actions after bootstrap. |
CERTBOT_EMAIL |
Let's Encrypt email. |
JWT_SECRET |
Stable production JWT signing secret. |
Server requirements:
- Clean Ubuntu/Debian-like server.
- DNS
Arecord forDEPLOY_DOMAINpointing atDEPLOY_HOST. - Ports
22,80, and443open. - Root SSH password login available for the first bootstrap.
See the full deployment guide:
- Set a long, random
JWT_SECRET. - Keep
JWT_SECRETstable across deployments; changing it logs users out. - Set
COOKIE_SECURE=truebehind HTTPS. - Restrict
CORS_ORIGINSto the production domain. - Back up the Docker volume containing
/data/tool_site.db. - Disable root password SSH after bootstrap if deploy key access works.
- Monitor nginx, Docker, disk usage, and certificate renewal.