feat: add website components and pages for LexAI
Some checks failed
CI — Chrome / Chrome — typecheck, test, build (pull_request) Has been cancelled
CI — CLI / CLI — typecheck, build, smoke (pull_request) Has been cancelled
CI — Website / Website — typecheck, build (pull_request) Has been cancelled
CI — VS Code / VS Code — typecheck, build (pull_request) Has been cancelled

- Implemented SiteHeader and SiteFooter components for consistent navigation and footer across the website.
- Created CommunityPage and ContributePage to provide information on community involvement and contribution guidelines.
- Developed DocsPage to serve as the main documentation hub, detailing features and installation instructions.
- Added HomePage to introduce LexAI and its functionalities, highlighting key features and privacy aspects.
- Established links.ts for centralized management of external links used throughout the website.
- Configured main.tsx for application entry point with React Router for navigation.
- Introduced styles.css for consistent styling across the website.
- Set up TypeScript configuration files for improved type checking and development experience.
- Configured Vite for building and serving the website.
This commit is contained in:
john kevin asprec
2026-08-13 20:27:55 +08:00
parent f5e24d8921
commit 5a79f1a2eb
31 changed files with 3541 additions and 19 deletions

View File

@@ -0,0 +1,83 @@
import { Link } from 'react-router-dom';
import {
CHROME_STORE,
REPO,
REPO_CONDUCT,
REPO_ISSUES,
REPO_LICENSE,
VSCODE_MARKETPLACE,
} from '../links';
export function CommunityPage() {
return (
<div className="wrap page">
<article className="docs-content">
<h1>Community</h1>
<p className="intro">
LexAI is maintained in the open. Use these links to install, report issues, and follow the
project.
</p>
<section className="docs-block" id="source">
<h2>Source &amp; discussion</h2>
<div className="package-grid">
<a className="package-card" href={REPO} target="_blank" rel="noreferrer">
<strong>Repository</strong>
<p>Source, issues, and pull requests on Gitea.</p>
<span className="more">git.juankibin.space/kibin/LexAI</span>
</a>
<a className="package-card" href={REPO_ISSUES} target="_blank" rel="noreferrer">
<strong>Bug report</strong>
<p>Use the issue template. Redact API keys.</p>
<span className="more">Open an issue</span>
</a>
<a className="package-card" href={REPO_CONDUCT} target="_blank" rel="noreferrer">
<strong>Code of Conduct</strong>
<p>Contributor Covenant. Be kind and stay on topic.</p>
<span className="more">Read</span>
</a>
</div>
</section>
<section className="docs-block" id="install">
<h2>Install channels</h2>
<ul>
<li>
<a href={CHROME_STORE} target="_blank" rel="noreferrer">
Chrome Web Store
</a>
</li>
<li>
<a href={VSCODE_MARKETPLACE} target="_blank" rel="noreferrer">
VS Code Marketplace
</a>{' '}
— <code>JuanKibin.lexai-vscode</code>
</li>
<li>
CLI — build from the repo (<Link to="/docs">docs</Link>)
</li>
</ul>
</section>
<section className="docs-block" id="audience">
<h2>Who it’s for</h2>
<p>
People who already hold an LLM API key and want inline writing or prompt help without a
SaaS subscription. Developers using Chrome, VS Code / Cursor, or a terminal agent loop.
</p>
</section>
<section className="docs-block" id="license">
<h2>License</h2>
<p>
LexAI is released under the{' '}
<a href={REPO_LICENSE} target="_blank" rel="noreferrer">
MIT License
</a>
.
</p>
</section>
</article>
</div>
);
}

View File

@@ -0,0 +1,88 @@
import { REPO, REPO_CONDUCT, REPO_CONTRIBUTING } from '../links';
export function ContributePage() {
return (
<div className="wrap page">
<article className="docs-content">
<h1>Contribute</h1>
<p className="intro">
LexAI is a monorepo: Chrome, VS Code, CLI, website, and a shared library. Please follow
the{' '}
<a href={REPO_CONDUCT} target="_blank" rel="noreferrer">
Code of Conduct
</a>
.
</p>
<section className="docs-block" id="ways">
<h2>Ways to help</h2>
<ul>
<li>Bug reports with reproduction steps</li>
<li>Documentation fixes</li>
<li>Small, focused pull requests (one concern per PR)</li>
<li>Design discussion when a change is large or security-sensitive</li>
</ul>
</section>
<section className="docs-block" id="setup">
<h2>Development setup</h2>
<p>Node.js 22+ and npm 11+.</p>
<pre className="mono">{`git clone https://git.juankibin.space/kibin/LexAI.git
cd LexAI
npm run install:all`}</pre>
<ul>
<li>
<code>npm run chrome:dev</code> / <code>chrome:test</code> /{' '}
<code>chrome:typecheck</code>
</li>
<li>
<code>npm run vscode:build</code> / <code>vscode:typecheck</code>
</li>
<li>
<code>npm run cli:build</code> / <code>cli:typecheck</code>
</li>
<li>
<code>npm run website:dev</code>
</li>
</ul>
<p>
Shared code lives in <code>src/lib/</code>. Do not import <code>@lib/crypto</code> or{' '}
<code>@lib/messaging</code> from VS Code or CLI.
</p>
</section>
<section className="docs-block" id="prs">
<h2>Pull requests</h2>
<ol>
<li>
Branch from <code>main</code> or <code>develop</code>.
</li>
<li>Keep the change scoped. Update docs when behavior changes.</li>
<li>Run the checks for the package you touched.</li>
<li>
Use the PR template in <code>.gitea/PULL_REQUEST_TEMPLATE.md</code>.
</li>
<li>Never commit API keys, tokens, or personal data.</li>
</ol>
</section>
<section className="docs-block" id="security">
<h2>Security</h2>
<p>
If you find a vulnerability around API-key handling or data exfiltration, do not open a
public issue with exploit details. Contact the maintainer privately (repository owner /
Chrome Web Store listing).
</p>
<div className="docs-meta">
<a className="btn btn-primary" href={REPO} target="_blank" rel="noreferrer">
Open the repository
</a>
<a className="btn btn-ghost" href={REPO_CONTRIBUTING} target="_blank" rel="noreferrer">
CONTRIBUTING.md
</a>
</div>
</section>
</article>
</div>
);
}

View File

@@ -0,0 +1,278 @@
import { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { CHROME_STORE, REPO, VSCODE_MARKETPLACE } from '../links';
function scrollToSection(id: string) {
document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
export function DocsPage() {
useEffect(() => {
const fromPath = window.location.href.match(/docs[#/]+([\w-]+)/i)?.[1];
const target = fromPath && fromPath !== 'docs' ? fromPath : undefined;
if (target) {
window.setTimeout(() => scrollToSection(target), 80);
}
}, []);
const nav = [
['overview', 'Overview'],
['chrome', 'Chrome'],
['vscode', 'VS Code'],
['cli', 'CLI'],
['shared', 'Shared core'],
['install', 'Install'],
['privacy', 'Privacy'],
] as const;
return (
<div className="wrap docs-layout">
<aside className="docs-nav" aria-label="Docs sections">
{nav.map(([id, label]) => (
<button key={id} type="button" className="nav-link-btn" onClick={() => scrollToSection(id)}>
{label}
</button>
))}
</aside>
<article className="docs-content">
<h1>Documentation</h1>
<p className="intro">
LexAI is an open-source, bring-your-own-LLM assistant. This page covers every package and
its features. Contributor setup lives on the{' '}
<Link to="/contribute">Contribute</Link> page.
</p>
<section className="docs-block" id="overview">
<h2>Overview</h2>
<p>
Three clients share one provider/prompt core. There is no LexAI backend — you supply an
API key for OpenAI, Anthropic, Groq, or OpenRouter.
</p>
<ul>
<li>
<strong>Chrome</strong> — writing help on any webpage
</li>
<li>
<strong>VS Code / Cursor</strong> — writing actions + workspace-aware Code Assist
</li>
<li>
<strong>CLI</strong> — Prompt Builder for the terminal
</li>
</ul>
</section>
<section className="docs-block" id="chrome">
<h2>Chrome extension</h2>
<p>
Manifest V3. Select text on any page, run an action, Replace or Copy. API key encrypted
locally with tweetnacl secretbox.
</p>
<h3>Setup</h3>
<p>
Options page → choose provider (OpenAI, Anthropic, Groq, or OpenRouter) and paste your
API key. There are no environment variables.
</p>
<h3>Features</h3>
<ul>
<li>Fix Grammar, Rephrase, Shorten, Expand, Explain, Make Prompt</li>
<li>Writing styles: Formal, Casual, Academic, Creative, Concise</li>
<li>Floating toolbar, right-click context menu, popup editor</li>
<li>Prompt Builder — patterns, persona, output format</li>
<li>Providers: OpenAI · Anthropic · Groq · OpenRouter</li>
<li>Works in text boxes, email composers, forms, and contenteditable pages</li>
</ul>
<div className="docs-meta">
<a className="btn btn-primary" href={CHROME_STORE} target="_blank" rel="noreferrer">
Chrome Web Store
</a>
<a
className="btn btn-ghost"
href={`${REPO}/src/branch/main/packages/chrome`}
target="_blank"
rel="noreferrer"
>
Package README
</a>
</div>
</section>
<section className="docs-block" id="vscode">
<h2>VS Code / Cursor extension</h2>
<p>
Editor twin of LexAI. Select text or code → action or Code Assist → Accept / Regenerate
/ Discard. Key lives in VS Code Secret Storage.
</p>
<p>
Published listing:{' '}
<a href={VSCODE_MARKETPLACE} target="_blank" rel="noreferrer">
JuanKibin.lexai-vscode
</a>
</p>
<h3>Setup</h3>
<p>
Command Palette → <code>LexAI: Open Settings</code> → provider, model, and API key.
The key is stored in VS Code Secret Storage. There are no environment variables.
</p>
<h3>Code Assist</h3>
<ul>
<li>Freeform instruction in an inline prompt above the selection</li>
<li>
Workspace context: surrounding code, imports, and symbol definitions from other files
</li>
<li>Entry points: CodeLens, context menu, Command Palette, Activity Bar sidebar</li>
</ul>
<h3>Writing actions</h3>
<ul>
<li>Fix Grammar · Rephrase · Shorten · Expand · Explain · Make Prompt</li>
<li>Writing styles + Prompt Builder option chips in the suggestion zone</li>
<li>Suggestion UI: zone (default), side panel, or both</li>
<li>Status bar: ready / processing / not configured</li>
<li>Sidebar workspace panel for paste → run → Copy</li>
</ul>
<div className="docs-meta">
<a className="btn btn-primary" href={VSCODE_MARKETPLACE} target="_blank" rel="noreferrer">
VS Code Marketplace
</a>
<a
className="btn btn-ghost"
href={`${REPO}/src/branch/main/packages/vscode`}
target="_blank"
rel="noreferrer"
>
Package README
</a>
</div>
</section>
<section className="docs-block" id="cli">
<h2>CLI — Prompt Builder</h2>
<p>
Improves a rough idea into a paste-ready engineered prompt before you send it to another
agent.
</p>
<h3>Setup</h3>
<p>Environment variables (PowerShell shown; bash uses <code>export NAME=value</code>):</p>
<pre className="mono">{`$env:LEXAI_API_KEY = "sk-..." # required
$env:LEXAI_PROVIDER = "openai" # optional: openai | anthropic | groq | openrouter
$env:LEXAI_MODEL = "gpt-4o" # optional`}</pre>
<p>
Optional defaults file (never put the API key here): <code>~/.lexai/config.json</code>
</p>
<pre className="mono">{`{
"provider": "openai",
"model": "gpt-4o",
"pattern": "role",
"persona": "Expert Developer",
"format": "Markdown",
"style": "Concise"
}`}</pre>
<p>
Precedence: flags → config file → env → defaults. The key is always{' '}
<code>LEXAI_API_KEY</code>.
</p>
<h3>Features</h3>
<ul>
<li>
Command: <code>lexai prompt</code>
</li>
<li>
Input from args, stdin, or <code>-f/--file</code>
</li>
<li>Flags: pattern, persona, format, style, provider, model</li>
<li>
Also <code>--list</code> (patterns, personas, formats, styles) and{' '}
<code>--help</code>
</li>
<li>Engineered prompt on stdout (pipe-safe); progress and errors on stderr</li>
</ul>
<h3>Examples</h3>
<pre className="mono">{`lexai prompt "add rate limiting to the express auth routes"
echo "debug flaky playwright on CI" | lexai prompt --pattern role
lexai prompt -f draft.txt --format Markdown --model gpt-4o`}</pre>
<div className="docs-meta">
<a
className="btn btn-ghost"
href={`${REPO}/src/branch/main/packages/cli`}
target="_blank"
rel="noreferrer"
>
Package README
</a>
</div>
</section>
<section className="docs-block" id="shared">
<h2>Shared core</h2>
<ul>
<li>
Location: <code>src/lib</code> (<code>providers</code>, <code>actions</code>,{' '}
<code>types</code>)
</li>
<li>Chrome-only modules: crypto (key encryption), messaging helpers</li>
<li>VS Code and CLI must not import Chrome-only modules</li>
</ul>
</section>
<section className="docs-block" id="install">
<h2>Install</h2>
<p>Published builds:</p>
<ul>
<li>
Chrome —{' '}
<a href={CHROME_STORE} target="_blank" rel="noreferrer">
Chrome Web Store
</a>
</li>
<li>
VS Code / Cursor —{' '}
<a href={VSCODE_MARKETPLACE} target="_blank" rel="noreferrer">
Visual Studio Marketplace
</a>{' '}
(<code>JuanKibin.lexai-vscode</code>)
</li>
</ul>
<p style={{ marginTop: '1rem' }}>From source (Node.js 22+):</p>
<pre className="mono">{`git clone https://git.juankibin.space/kibin/LexAI.git
cd LexAI
npm run install:all
# Chrome
npm run chrome:dev # or chrome:build → load packages/chrome/.output/chrome-mv3
# VS Code
npm run vscode:build # or install from Marketplace
# CLI
npm run cli:build
export LEXAI_API_KEY=sk-... # required
export LEXAI_PROVIDER=openai # optional: openai | anthropic | groq | openrouter
export LEXAI_MODEL=gpt-4o # optional
node packages/cli/out/cli.js prompt "your rough idea"
# Website
npm run website:dev`}</pre>
</section>
<section className="docs-block" id="privacy">
<h2>Privacy</h2>
<ul>
<li>No LexAI backend, account, or subscription</li>
<li>No LexAI telemetry</li>
<li>
Chrome: encrypted key in <code>chrome.storage.local</code>
</li>
<li>VS Code: Secret Storage</li>
<li>
CLI: <code>LEXAI_API_KEY</code> required; optional <code>LEXAI_PROVIDER</code> and{' '}
<code>LEXAI_MODEL</code>. Never store the key in <code>~/.lexai/config.json</code>
</li>
<li>Text is sent only to the LLM provider you configure</li>
</ul>
</section>
</article>
</div>
);
}

View File

@@ -0,0 +1,175 @@
import { Link, useNavigate } from 'react-router-dom';
import { LogoMark } from '../components/LogoMark';
import { CHROME_STORE, REPO, VSCODE_MARKETPLACE } from '../links';
function openDocsSection(navigate: ReturnType<typeof useNavigate>, id: string) {
navigate('/docs');
window.setTimeout(() => {
document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, 60);
}
const FEATURES = [
{
title: 'Your key. Your provider.',
body: 'OpenAI, Anthropic, Groq, or OpenRouter. No LexAI account or servers.',
},
{
title: 'Writing help, like Grammarly',
body: 'Select text on any page → Fix, Rephrase, Shorten, Expand, Explain, or Make Prompt.',
},
{
title: 'Coding assist, like Copilot',
body: 'VS Code and Cursor: select code, give an instruction, apply a suggestion with file context.',
},
{
title: 'Prompt Builder',
body: (
<>
Turn a rough idea into a paste-ready prompt — in the app or via <code>lexai prompt</code>.
</>
),
},
{
title: 'Private by design',
body: 'Keys stay on your device. Text goes only to the provider you choose.',
},
{
title: 'Open source (MIT)',
body: 'Chrome, VS Code, and CLI share one core. Audit it, fork it, ship your own build.',
},
];
export function HomePage() {
const navigate = useNavigate();
return (
<>
<section className="hero">
<div className="wrap">
<div className="hero-lockup">
<LogoMark size={48} />
<p className="hero-wordmark">
Lex<span>AI</span>
</p>
</div>
<p className="hero-kicker">Bring your own LLM</p>
<h1>Skip Grammarly and Copilot subscriptions</h1>
<p className="hero-lead">
Writing help on any webpage. Coding assist in VS Code or Cursor. You bring the API key —
LexAI has no account, no servers, and no fee.
</p>
<div className="cta-row">
<a className="btn btn-primary" href={CHROME_STORE} target="_blank" rel="noreferrer">
Chrome Web Store
</a>
<a className="btn btn-ghost" href={VSCODE_MARKETPLACE} target="_blank" rel="noreferrer">
VS Code Marketplace
</a>
<a className="btn btn-ghost" href={REPO} target="_blank" rel="noreferrer">
Repository
</a>
<Link className="btn btn-ghost" to="/docs">
Docs
</Link>
</div>
</div>
</section>
<section className="section" id="why">
<div className="wrap">
<p className="section-kicker">Why try it</p>
<h2>The jobs you already pay for — without a second subscription</h2>
<p className="section-lead">
Same idea as the tools you know. You pay your LLM provider, not LexAI.
</p>
<div className="compare-grid">
<div className="package-card">
<strong>Instead of Grammarly</strong>
<p>
Fix grammar, rephrase, shorten, expand, or explain on any webpage. Your key stays on
your device.
</p>
<span className="more">Chrome extension</span>
</div>
<div className="package-card">
<strong>Instead of GitHub Copilot</strong>
<p>
Select code, type what you want, and apply a suggestion with context from other
files. Not tab-complete — instruct and review.
</p>
<span className="more">VS Code / Cursor</span>
</div>
</div>
</div>
</section>
<section className="section" id="features">
<div className="wrap">
<p className="section-kicker">Product</p>
<h2>What LexAI does</h2>
<p className="section-lead">
One family across browser, editor, and CLI. Same providers. No LexAI backend.
</p>
<ul className="feature-list">
{FEATURES.map((f) => (
<li key={f.title}>
<h3>{f.title}</h3>
<p>{f.body}</p>
</li>
))}
</ul>
</div>
</section>
<section className="section" id="start">
<div className="wrap">
<p className="section-kicker">Getting started</p>
<h2>Install in minutes</h2>
<p className="section-lead">Published builds, or clone the repo if you want to develop.</p>
<div className="package-grid">
<a className="package-card" href={CHROME_STORE} target="_blank" rel="noreferrer">
<strong>Chrome</strong>
<p>Install from the Chrome Web Store. Set provider and API key in Options.</p>
<span className="more">Chrome Web Store</span>
</a>
<a className="package-card" href={VSCODE_MARKETPLACE} target="_blank" rel="noreferrer">
<strong>VS Code</strong>
<p>
Install <code>JuanKibin.lexai-vscode</code>. Open Settings, add your key, select
code.
</p>
<span className="more">Marketplace</span>
</a>
<button
type="button"
className="package-card"
onClick={() => openDocsSection(navigate, 'cli')}
>
<strong>CLI</strong>
<p>
Build <code>lexai prompt</code>, set <code>LEXAI_API_KEY</code> and optional{' '}
<code>LEXAI_PROVIDER</code> / <code>LEXAI_MODEL</code>.
</p>
<span className="more">CLI docs</span>
</button>
</div>
</div>
</section>
<section className="section">
<div className="wrap privacy">
<p className="section-kicker">Privacy</p>
<h2>No LexAI cloud</h2>
<ul>
<li>Your API key never leaves your device except to the provider you configure.</li>
<li>No LexAI telemetry and no LexAI servers in the path.</li>
<li>
Open source — inspect the shared core in <code>src/lib</code>.
</li>
</ul>
</div>
</section>
</>
);
}