Project Info
Inspiration
News articles often contain many factual claims, but a simple “true” or “false” label does not explain what is actually wrong. We wanted to build a tool that shows which specific claims require attention, what the available evidence says, and why a particular verdict was reached. What We Built FactCheck is a Chrome extension for checking news articles directly in the browser. It can analyze the text of an open article or check a single claim entered by the user. The system identifies up to three independently checkable claims, searches Google Fact Check Tools and Tavily for relevant evidence, ranks sources by relevance and credibility, compares claims with the retrieved evidence, and displays verdicts, explanations, confidence scores, citations, and source links. The project consists of: a React and TypeScript Chrome extension with a browser side panel; a Spring Boot backend that coordinates the fact-checking pipeline; a FastAPI model service using Qwen for claim extraction; DeBERTa for comparing claims with evidence; evidence retrieval through Google Fact Check Tools and Tavily. OpenAI Build Week We developed FactCheck during OpenAI Build Week. OpenAI Codex and ChatGPT supported our development process by helping us analyze the repository, design the API architecture, debug integration issues, create tests, and improve the project documentation. What We Learned We learned how to connect a browser extension with multiple backend services, design stable API contracts, process model responses, and handle uncertainty in automated fact-checking. We also learned that an AI-generated verdict should not rely only on a model’s internal knowledge. It should be connected to real, traceable sources and clearly show the evidence used to support or challenge a claim. Challenges The main challenge was coordinating several independent components: the Chrome extension, Spring Boot backend, external evidence providers, and AI inference service. We also had to handle slow model cold starts, unavailable external APIs, missing evidence, differences in source credibility, and invalid model responses. Another challenge was making the results understandable. Instead of returning only a final label, the system shows the exact claim, evidence excerpts, an explanation, a confidence score, and links to the original sources. Future Improvements Future versions could improve multilingual claim extraction, strengthen contextual manipulation detection, add more evidence providers, improve source verification, support analysis history, and provide more detailed explanations when the available evidence is conflicting or inconclusive.
FactCheck
FactCheck is a Chrome extension for checking claims in news articles. The current repository contains three cooperating applications:
- a React/Vite Chrome extension that runs in the browser side panel;
- a Spring Boot backend that searches for evidence, ranks sources, and coordinates the fact-check;
- a FastAPI model service that uses Qwen for claim extraction and DeBERTa for claim/evidence comparison.
This is a working local prototype, not a production fact-checking authority. Its verdicts depend on the claims extracted, the evidence returned by external search providers, and domain-level source credibility heuristics. Always open the cited sources before treating a result as conclusive.
Current features
- Article mode: reads the active article and extracts up to three independently checkable claims.
- Single-claim mode: checks the exact statement entered by the user without splitting or rewriting it into subclaims.
- Evidence retrieval: searches Google Fact Check Tools and Tavily, then deduplicates and relevance-ranks up to three sources per claim. Transient Tavily failures are retried once, and either provider can work as a fallback when the other is unavailable.
- Source evaluation: weights model comparisons by a transparent domain-level credibility assessment, so a Reddit post is not treated like an official record or an established publisher.
- Results: shows a verdict, percentage, explanation, evidence excerpts, clickable citations, and a credibility label for each source.
- Source tracing: selects the earliest dated credible result when possible, or the best available search result, and labels it as the likely original source.
- Distortion reporting: automatically marks a factual contradiction when a refuted claim conflicts with the traced source. The backend and UI also support context-distortion results, although the current comparison logic does not generate manipulation verdicts automatically.
- Article highlights: highlights checked claims in the page and colors them by verdict: green for confirmed, red for refuted, orange for manipulation, and yellow for insufficient evidence. Clicking a highlight opens its evidence details.
How We Used OpenAI Codex
We used OpenAI Codex throughout development as an engineering and product design assistant. Codex helped us analyze the existing repository, shape the extension and backend architecture, and divide the implementation into clear modules for the team.
For the frontend, Codex supported the side-panel layout, responsive states, article and single-claim flows, loading and error states, and the presentation of verdicts, confidence scores, evidence excerpts, citations, and source credibility. It also helped us refine the visual hierarchy and make the result cards easier to scan.
For the backend and model integration, Codex helped implement and debug the REST API, validation, CORS, caching, AI client abstraction, evidence pipeline, remote model API integration, and error handling. It also helped create tests, diagnose Windows and PowerShell setup issues, verify service communication, and keep the local and hosted run instructions up to date.
Codex was used as a development assistant; the runtime fact-checking pipeline uses Qwen for claim extraction and DeBERTa for claim/evidence comparison.
Architecture
flowchart LR
Page["Open article or manual claim"] --> Extension["Chrome side panel"]
Extension --> Backend["Spring Boot API :8080"]
Backend --> Qwen["Qwen claim extraction"]
Backend --> Search["Evidence search and ranking"]
Search --> Google["Google Fact Check Tools"]
Search --> Tavily["Tavily"]
Backend --> DeBERTa["DeBERTa comparison via FastAPI :7860"]
Backend --> Extension
Extension --> Highlights["Colored, clickable page highlights"]
For an article request, the backend asks Qwen for at most three claims. For a
manual request, it skips extraction and preserves the submitted claim. Each
claim is searched independently and compared with the returned evidence using
MoritzLaurer/DeBERTa-v3-base-mnli-fever-anli.
The backend multiplies each comparison score by the source credibility weight
before deciding a verdict. The strongest adjusted support and contradiction
scores are compared with a 0.55 decision threshold.
| Source category | Weight | Examples |
|---|---|---|
| Professional fact-check result | 1.00 | Result returned by Google Fact Check Tools |
| Official source | 0.98 | Government, court, university, EU, UN, or WHO domains |
| Established fact-check publisher | 0.95 | FactCheck.org, Full Fact, PolitiFact, Snopes |
| Established news publisher | 0.85 | AP, BBC, Reuters, and the maintained news-domain list |
| Unrated site | 0.55 | A domain without a configured rating |
| Community or social platform | 0.15 | Reddit, Facebook, X, YouTube, and similar platforms |
| Satire publisher | 0.05 | The Onion, Babylon Bee |
These weights are heuristics for source provenance, not a judgment that every
page from a listed domain is correct. If credible evidence strongly supports
and contradicts the same claim, the backend returns
INSUFFICIENT_EVIDENCE for human review.
The source trace is also intentionally cautious. It chooses among sources returned by the configured search providers; it does not prove that the chosen page was the first publication anywhere on the web.
Completed responses with evidence for every claim are cached in memory for ten minutes, up to 100 entries. Empty-evidence responses are not cached, so a temporary search-provider failure can recover on the next request.
Run with the hosted services (recommended)
The intended way to run FactCheck is to build only the Chrome extension and use the already deployed backend and model API:
| Service | Public URL |
|---|---|
| Spring backend | https://fake-check-extension.onrender.com |
| Model API | https://sickadenis--facttrace-ai-api.modal.run |
The extension sends fact-check requests to the Render backend, and the backend calls the Modal model API. You do not need to run Java or Python locally for this setup.
From the repository root, install and build the extension against the hosted backend:
npm install --prefix extension
VITE_FACTCHECK_API_URL=https://fake-check-extension.onrender.com npm run build
To keep the hosted URL for future Vite builds, create
extension/.env.local containing:
VITE_FACTCHECK_API_URL=https://fake-check-extension.onrender.com
Load the built extension in Chrome:
- Open
chrome://extensions. - Enable Developer mode.
- Select Load unpacked.
- Choose
extension/dist. - Click the FactCheck toolbar icon to open the side panel.
After rebuilding, click the extension reload button on
chrome://extensions. Chrome asks for optional access to a website the first
time FactCheck reads it; browser-internal pages cannot be inspected.
You can verify the hosted services with:
curl https://fake-check-extension.onrender.com/api/health
curl https://sickadenis--facttrace-ai-api.modal.run/health
Both hosts can have a cold start after being idle, so the first request can take longer than later requests.
Self-hosting fallback
Use the following setup if a hosted service is unavailable or if you need to develop the backend or model service locally.
Configure environment variables
Create the local environment file from the committed template:
cp .env.example .env
The complete evidence pipeline uses:
GOOGLE_FACTCHECK_API_KEYfor Google Fact Check Tools;TAVILY_API_KEYfor Tavily.
The backend still works when only one provider is configured. If neither
provider returns usable evidence, the result is INSUFFICIENT_EVIDENCE.
The root scripts load .env automatically:
| Variable | Default | Used by |
|---|---|---|
FACTCHECK_AI_MODE | mock | Spring backend; use remote for real model inference |
FACTCHECK_AI_BASE_URL | http://localhost:7860 | Spring backend |
GOOGLE_FACTCHECK_API_KEY | empty | Spring backend |
TAVILY_API_KEY | empty | Spring backend |
CLAIM_MODEL_ID | Qwen/Qwen2.5-1.5B-Instruct | Python model service |
NLI_MODEL_ID | MoritzLaurer/DeBERTa-v3-base-mnli-fever-anli | Python model service |
MAX_ARTICLE_TOKENS | 8192 | Python model service |
MAX_NEW_TOKENS | 384 | Python model service |
NLI_DECISIVE_SCORE | 0.55 | Python model service |
The local Spring backend can still use the deployed model API instead of running the models locally:
https://sickadenis--facttrace-ai-api.modal.run
To use it, configure the backend with:
FACTCHECK_AI_MODE=remote
FACTCHECK_AI_BASE_URL=https://sickadenis--facttrace-ai-api.modal.run
Install the full local stack
From the repository root:
npm install --prefix extension
cd ai-service
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
cd ..
The first model request downloads several gigabytes. Models load lazily, so the first claim extraction and first evidence comparison are slower than later requests.
Run every service locally
Use three terminal windows from the repository root.
Terminal 1 — start the model service on port 7860:
source ai-service/.venv/bin/activate
npm run ai:run
Terminal 2 — start the Spring backend on port 8080:
npm run backend:run
Terminal 3 — build the extension and watch for frontend changes:
npm run dev
Check that both services are available:
curl http://localhost:7860/health
curl http://localhost:8080/api/health
The model service OpenAPI documentation is available at
http://localhost:7860/docs.
After changing from the hosted backend to the local backend, rebuild and reload
the extension using the Chrome steps above. Open a normal http:// or
https:// article and choose Fact-check this article, or switch to
Single claim and enter one statement.
Mock mode
To run the backend without the Python models, set:
FACTCHECK_AI_MODE=mock
Mock mode is useful for UI work, but it does not perform real claim extraction or evidence comparison. Restart Spring after changing the mode because the AI client is selected during application startup.
Use the local backend in the extension
The API URL is a Vite build-time value. To switch from the hosted backend to a local backend, rebuild with:
VITE_FACTCHECK_API_URL=http://localhost:8080 npm run build
You can also put the value in extension/.env.local. For any other non-local
API, add that origin to host_permissions in
extension/public/manifest.json, rebuild, and reload the extension.
Port 8080 is already in use
lsof -nP -iTCP:8080 -sTCP:LISTEN
kill <PID>
npm run backend:run
HTTP API
Fact-check an article
curl -X POST http://localhost:8080/api/fact-check \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com/article",
"title": "Example article",
"text": "The complete article text goes here."
}'
Fact-check one unchanged claim
curl -X POST http://localhost:8080/api/fact-check \
-H 'Content-Type: application/json' \
-d '{
"text": "The exact claim to check.",
"singleClaim": true
}'
Inspect ranked evidence
curl -X POST http://localhost:8080/api/evidence/search \
-H 'Content-Type: application/json' \
-d '{"claim":"The Earth is flat"}'
Search Tavily directly
curl -X POST http://localhost:8080/api/websearch/search \
-H 'Content-Type: application/json' \
-d '{"claim":"The Earth is flat"}'
Build and test
npm run typecheck
npm run test
npm run build
npm run backend:test
npm run backend:package
npm run ai:test
Repository layout
extension/ React/Vite Chrome extension
backend/ Spring Boot orchestration and evidence API
ai-service/ FastAPI model inference service and deployment files
Analysis
View
Metric
- 20
- 4
- 2
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- FastAPIIn code
- HTMLIn code
- Hugging FaceIn code
- JavaIn code
- PythonIn code
- PyTorchIn code
- ReactIn code
- TypeScriptIn code
- DockerClaimed
9 of 10 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
No AI coding agent signals were found in this repository.
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
264 KB
Source files
84
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
alienqqe/fake-check-extension
112 files · 347 KB · @ 989b219
Structure
Interface
15 files · 13%Screens, components and styles rendered to the user.
API & routing
1 file · 1%Request entry points: routes, handlers and controllers.
Application logic
56 files · 50%Domain rules, services and shared utilities.
+1 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Java58%
- TypeScript17%
- Python13%
- Markdown6%
- CSS5%
- XML1%
- Other (1)0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
extension/package.json
npm · 10- react
- react-dom
- +8 more
ai-service/requirements.txt
pypi · 7- accelerate
- fastapi
- pydantic
- sentencepiece
- torch
- transformers
- uvicorn[standard]
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.