DeepChat sends every question to two AIs. DeepSeek answers; ChatGPT gets the question and the answer and returns a review with a verdict (correct, partially correct or incorrect), the strong points, what to improve and, when needed, a corrected version. Instead of trusting a single AI, you see the answer and its check side by side.
It runs entirely in the browser, with plain JavaScript: no framework, no build step and no server. Questions go straight from the browser to the APIs. The interface is in Portuguese.
Open DeepChat · See the demo, no keys needed: three sample conversations, where nothing is sent or saved.
This README is also available in Portuguese.
- Open the demo. It starts on a question where the answer repeats a myth, and the review marks it Incorreta (incorrect).
- In the sidebar, open the CPF conversation (CPF is the Brazilian taxpayer
ID): the review finds a real bug in the code (the function accepts
111.111.111-11) and brings the fixed version. - In Nova conversa (New conversation), pick a sample question and watch the answer and the review arrive.
Taken from the demo mode.
| Conversation, dark theme | Code review, light theme |
|---|---|
![]() |
![]() |
| Start screen, light theme | New conversation, dark theme |
![]() |
![]() |
| On a phone, light theme | On a phone, dark theme |
|---|---|
![]() |
![]() |
- DeepSeek answers. ChatGPT reviews in a fixed format: verdict, accuracy, strong points, what to improve, suggestions and, only when there is an error or an important gap, a revised version (collapsed, to expand).
- One click on the question box swaps the order: ChatGPT answers and DeepSeek reviews.
- Outra resposta (Another answer), on the latest answer, asks again for a different take and reviews it again.
- Citar (Quote) brings a passage of any answer or review into the next question, and the passage is sent to the AI too.
- The answer shows up word by word, and so does the review: the verdict appears as soon as its first line arrives. Meanwhile, the question box shows who is working and for how long.
- The reviewed answer gets a line in the margin in the verdict's color, like a proofreader's mark.
- You can stop at any time, with the button or Esc. Whatever already arrived stays in the conversation, marked, and is not reviewed.
- Code blocks are colored (JavaScript, TypeScript, Python, SQL, shell, JSON, YAML, CSS, HTML and the C family) and have a copy button.
- Text and code files (TXT, MD, CSV, JSON, JS, PY and more, up to 5 MB): the content goes to the one answering and to the reviewer. Only the first 20,000 characters are sent; for a bigger file, the app says so.
- Images (PNG, JPG, WebP, GIF), scaled down to 1024 px before sending, when ChatGPT answers. DeepSeek cannot read images; the app says so and offers to swap the order.
- With the paperclip, by pasting (Ctrl+V) or by dropping onto the chat.
- Each error is explained in Portuguese: rejected key (with a shortcut to the key settings), no credits or over the rate limit, timeout, network failure, service down.
- If only the review fails, the answer stays, and the notice offers Revisar agora (Review now).
- Network failures, timeouts and 5xx errors get up to three attempts, with growing waits, as long as no text has arrived. If the connection drops in the middle of an answer, what arrived stays, and the notice offers Tentar de novo (Try again). When three questions in a row fail on the same API, the app waits 30 s before calling it again.
- The timeout is 60 s without receiving anything; each piece that arrives resets it.
- An unexpected failure is logged in the browser and shows up in Sobre › Diagnóstico (About › Diagnostics), ready to copy.
- Conversations are saved in the browser, grouped by date, with search over titles and text. Deleting has Desfazer (Undo).
- Export as Markdown, and print or save as PDF with a layout made for paper.
- The question draft is kept while the tab is open.
- Conversations saved by the previous version of the app are converted automatically.
- Light, dark or system theme, with no flash on load.
- On a phone, the conversation list becomes a drawer and dialogs become bottom sheets.
- Keyboard: Enter sends, Shift+Enter adds a line break, Ctrl+K starts a new conversation and Esc stops the answer. The menu works with arrow keys.
- Screen readers are told when the answer and the review arrive, with the verdict.
- Respects "reduce motion" and the system's high-contrast mode.
- No server. Questions go from the browser straight to
api.deepseek.comandapi.openai.com. Each question is billed to your own account on each service. - Keys. "Lembrar neste navegador" (Remember in this browser) comes
unchecked: the keys last until the page is reloaded or closed. If you
check it, the keys are encrypted with AES-GCM using a random key that the
browser cannot export (a non-extractable
CryptoKey, kept in IndexedDB); only the encrypted text goes tolocalStorage. This keeps the keys unreadable in a backup, a copy of the browser profile or a quick look at storage. It does not protect against code running on this same origin: that code cannot read the encryption key, but it can ask the browser to decrypt with it. The originalyssom-fernandes.github.iois shared with other projects of the author, so only check the option on a computer that is yours alone. If saved keys cannot be opened (for example, after the site data was partly cleared), the app says so and asks you to paste them again. Vaults saved by earlier versions, with a password derived from the browser, are opened once and converted. Keys with a spending limit are a good idea. - AI content. Markdown goes through DOMPurify; every outside text (question, file name, title) is escaped before it becomes HTML.
- Content Security Policy without
'unsafe-inline', with connections allowed only to the two APIs.markedand DOMPurify are pinned and loaded with Subresource Integrity (SRI). The 404 page allows its inline script and style by hash, and a test checks those hashes. - What else the page loads. Only the two Markdown libraries, from
jsDelivr, which sees the visitor's IP address, never the conversations.
The fonts are served by the site itself. No request sends the page
address (
Referer), not even to the APIs. - Inside another site. In an iframe, DeepChat does not ask for or open the keys (GitHub Pages cannot send the header that blocks framing); it offers to open in its own tab. The demo, which has no keys, still opens.
| Part | Technology |
|---|---|
| Interface | HTML, CSS and JavaScript ES modules, no framework and no build |
| Markdown | marked 9 and DOMPurify 3, from jsDelivr, with SRI |
| APIs | streaming fetch (Server-Sent Events) straight to DeepSeek (deepseek-chat) and OpenAI (GPT-4o mini or GPT-4o) |
| Code colors | js/realce.js, no library |
| Data | localStorage for history and preferences; WebCrypto for the keys |
| Fonts | Instrument Sans for the interface; JetBrains Mono for code and the signature, served by the site itself (OFL license) |
| Tests | node --test, no dependencies, on every push (GitHub Actions) |
Some decisions behind it:
- The review has a fixed format, and the screen reads it. That is how the verdict stands out and each part lands in its place. If the model strays from the format, the review is shown whole, as plain text; the old emoji format is read too.
- The answering AI does not see past reviews. The context it gets has only the questions and answers; the reviewer gets the question, the answer, a summary of the conversation and the attachment. Fewer tokens, and each AI in its own role.
- The demo is tested. The samples were written to show the app, and the tests check that what they claim is true: they run the CPF function from the answer and the one from the review, and redo the interest math.
- The parts that decide what shows up are pure, tested functions: review parsing (new and old format), history migration, the context sent to the APIs, Markdown export, search, dates and text helpers.
- The key vault is tested in Node. With a fake
localStorageand a fake IndexedDB (and the realcrypto.subtle), the tests cover encrypting and decrypting, migration from the old format, failure to open and forgetting the keys. - Streaming is tested without a network. A fake
fetchdelivers the answer in pieces, drops the connection midway and answers with errors; the tests check the assembled text, and when a retry happens and when it does not. - Code colors without a library. A small reader per language family, instead of one more outside script in the CSP. The tests check that the code on screen is identical to what the AI sent and that none of it becomes HTML.
- You need an API key for each service, with credits. Without them, only the demo works.
- DeepSeek cannot read images. PDFs are not accepted: for a PDF, copy its text into a TXT file.
- Saved keys depend on the encryption key kept in this browser. If the site
data is cleared in part (IndexedDB gone,
localStoragekept), the keys cannot be opened and you paste them again. - History stays in this browser only. Clearing the site's data erases it; to keep a conversation, export it as Markdown.
markedand DOMPurify come from a CDN. Without them, Markdown falls back to a simple, safe format.- The interface is in Portuguese only.
The app uses ES modules, which browsers do not load straight from disk
(file://). Serve the folder with any static server, for example:
python -m http.server 8000and open http://localhost:8000. To publish it, GitHub Pages serves the
folder as is.
To run the tests (Node 22 or newer, nothing to install):
node --testindex.html the page: start screen, conversation and dialogs
404.html page for addresses that do not exist
css/style.css light and dark themes, phone and print
js/
boot.js theme before the page shows up, and the failure log
app.js question → answer → review flow, events and dialogs
ui.js messages, review, notices, history and toasts
api-client.js API calls: streaming, retries, timeout, circuit breaker, attachments
realce.js colors for code blocks
revisao.js prompts and review parsing (verdict and sections)
conversa.js conversation model, migration, context and export
storage.js encrypted keys, preferences and history
state.js session state
texto.js text, dates and sizes
demo.js demo conversations
fonts/ Instrument Sans and JetBrains Mono, with their OFL licenses
tests/ tests for the pure functions, streaming (fake fetch) and the CSP
.github/workflows/ runs the tests on every push
docs/telas/ images for this README and the link preview (og.png)
MIT. Made by Alyssom Fernandes, AFN Systems.






