Skip to content

About

My resume website :)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

117 Commits

Folders and files

Repository files navigation

πŸ–₯️ ZQS Terminal β€” Rust RΓ©sumΓ© in Your Browser

Netlify Status WebAssembly Rust

An immersive single-page web terminal that reveals Alexandre DO-O ALMEIDA’s rΓ©sumΓ© through typed commands. Everything is written in Rust, compiled to WebAssembly, and ships as a framework-free SPA for fast cold starts.

ZQS Terminal landing screen

✨ Features

  • πŸŽ›οΈ Web-only terminal UI with history, autocomplete, theming, achievements, and an AI Mode toggle.
  • πŸ“¦ Static rΓ©sumΓ© data sourced from JSON so updates never require a recompile.
  • πŸ€– Optional AI concierge proxied through an Axum service that uses complete curated knowledge and persistent spending limits.
  • πŸš€ Build pipeline ships optimized WebAssembly + minified CSS in static/, ready for any CDN with an optional Axum proxy.

πŸ€– AI Concierge Stack

  • Generation: one OpenAI gpt-5.6-luna call, Chat Completions with reasoning none and a 640-token output cap.
  • Knowledge: all seven curated JSON sources, including expanded projects, publications, awards and testimonials beyond the one-page CV. No paid retrieval or vector database is needed.
  • Follow-ups: the last three exchanges are kept in tab memory, bounded and validated by the server. quit or refresh clears them.
  • Reliability: pre-call rate/concurrency limits, a 16-second server deadline, a 20-second browser deadline and a working classic terminal on failure.
  • Spending: persistent USD ledger, conservative reservation followed by one reconciliation against reported input/output/cache usage. $0.50/minute, $2/hour and day, $10/30 days by default.
  • Attribution: sources contains validated section IDs, shown below each answer. Factual evaluation remains necessary; metadata alone does not establish correctness.

πŸ—‚οΈ Repository Layout

.
β”œβ”€β”€ Cargo.toml            # Workspace root + WebAssembly crate manifest
β”œβ”€β”€ VERSION               # Project version (sync via scripts/bump_version.py)
β”œβ”€β”€ Makefile              # Build/test/deploy entry points (wasm-pack, Netlify, logs)
β”œβ”€β”€ netlify.toml          # Netlify deploy config (redirects, cache headers)
β”œβ”€β”€ .env.example          # Template for required/optional environment variables
β”œβ”€β”€ src/                  # Rust/WebAssembly terminal (commands, state, renderer)
β”œβ”€β”€ server/               # Axum proxy (OpenAI relay, rate limiting, static host)
β”œβ”€β”€ static/
β”‚   β”œβ”€β”€ index.html        # Terminal shell + module bootstrap
β”‚   β”œβ”€β”€ style.css         # Source stylesheet (minified to style.min.css)
β”‚   β”œβ”€β”€ style.min.css     # Minified styles generated by make build
β”‚   β”œβ”€β”€ data/             # RΓ©sumΓ© JSON (profile, skills, experience, education, projects)
β”‚   β”œβ”€β”€ images/           # Logos & Open Graph artwork
β”‚   β”œβ”€β”€ icons/            # Favicons & manifest assets
β”‚   β”œβ”€β”€ effects/          # Visual flourish assets (canvas, particles, etc.)
β”‚   β”œβ”€β”€ cv/               # Canonical HTML resume, PDF download and local assets
β”‚   └── pkg/              # wasm-bindgen output mirrored from /pkg
β”œβ”€β”€ pkg/                  # Raw wasm-pack artefacts (ignored by git)
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ bump_version.py   # Bumps VERSION + Cargo manifests
β”‚   β”œβ”€β”€ live_smoke_test.py  # Production smoke test
β”‚   β”œβ”€β”€ minify_css.py     # CSS minifier invoked by make build
β”‚   β”œβ”€β”€ run_live_autotest.sh  # CI helper for the smoke test
β”‚   └── serve.py          # Static dev server (writes server.log)
└── screenshot_zqsdev.png # README showcase image

πŸš€ Quick Start

Install the prerequisites once:

rustup target add wasm32-unknown-unknown
cargo install wasm-pack

Fetch dependencies and build the terminal bundle:

make build

⌨️ Commands

Inside the terminal, try:

help        about       skills       experience
education   projects    testimonials contact
faq         resume      theme        ai
clear

Flip on AI Mode with the toolbar button to ask natural-language questions. When disabled, helper chips provide quick access to the commands above.

πŸ› οΈ Development Workflow

# 1. Compile the WebAssembly bundle (writes static/pkg/)
make build

# 2. Run the full Rust stack (serves static assets + /api/ai)
export OPENAI_API_KEY=sk-your-key   # required for AI mode
make serve                          # http://localhost:3000 by default

# Optional: static-only dev server (no AI proxy, logs to server.log)
make serve-static                   # http://localhost:8765 by default

Useful overrides:

make serve HOST=127.0.0.1 SERVER_PORT=4000
make serve-static STATIC_PORT=9000

make build always refreshes static/pkg/ and static/style.min.css, both of which must ship alongside the rest of static/ for deployment.

πŸ“š Curated knowledge

Edit static/data/*.json, run python3 scripts/validate_knowledge.py, build, and restart the backend after deploying data. The reviewed full-context ceiling is 64 KB. Builds require no AI credentials.

The migration verified all 44 live SQLite chunks against the JSON sources and the Pinecone index held 44 vectors. All original projects (including Micro Mages, Mistale, BeeToBee and TheClair), education, publications, awards and two full testimonials were preserved. The obsolete terminal-project description, role dates and availability FAQ were updated; Studi and agentic engineering were added.

Legacy build_rag.py, inspect_rag.py and make rag remain available for historical inspection only. Normal build and runtime never query Pinecone, call embeddings or open SQLite. The old index is left intact.

Official model reference: GPT-5.6 Luna. Rates verified on 2026-09-08: input $0.20, cache read $0.02, cache write $0.25, output $1.20 per million tokens. Set all rates explicitly when selecting another model.

βœ… Tests & Quality Gates

make test   # wasm-pack test --node + cargo test for the proxy
make fmt    # cargo fmt across the workspace
make check  # cargo check --target wasm32-unknown-unknown

The CI pipeline should run the same trio so local runs stay in lockstep with automation.

🩺 Live Production Smoke Test

Run make autotest (or directly python3 scripts/live_smoke_test.py) to exercise the deployed site once end-to-end. It validates the Netlify bundle, the /api/data payloads, and sends two questions to the AI concierge. Install the lone dependency with pip install requests, then wire either command into your scheduler (cron, GitHub Actions, etc.). Optional flags:

python3 scripts/live_smoke_test.py --json-output live-smoke.json
python3 scripts/live_smoke_test.py --ai-question "What's new with Alexandre?"
# Or via make (flags are forwarded):
make autotest AUTOTEST_FLAGS="--json-output live-smoke.json"

The script exits non-zero on failure so monitors can trigger alerts. Keep the two-question smoke suite bounded to respect the production rate limits. For cron jobs, scripts/run_live_autotest.sh wraps the Python entry point with sensible defaults.

If PUSHOVER_API_TOKEN and PUSHOVER_USER_KEY are present (in the environment, .env.local, or .env), the script will send a Pushover alert only when a check fails or the run ends early with skipped tests. Disable that behaviour with --no-pushover or AUTOTEST_FLAGS="--no-pushover" if needed.

πŸ”‘ Environment Variables

  1. Copy the template:
    cp .env.example .env
  2. Update at least OPENAI_API_KEY=... if you plan to enable AI Mode locally.

OPENAI_API_KEY is the only required secret today. No other AI provider or vector-database credentials are needed. The proxy loads .env.local first, then .env, which keeps machine-specific overrides out of version control. Both files are ignored by git so real keys stay on your machine.

πŸ“¦ Versioning & Release Workflow

  • βœ… Run make build and make test before handing changes off so static/pkg/ and the proxy both stay green.
  • ⬆️ Bump the version with python3 scripts/bump_version.py (touches VERSION, Cargo.toml, and server/Cargo.toml). The script defaults to patch releases; pass --minor or --major when needed.
  • ✍️ Commit only the sources, regenerated assets under static/pkg/, and version bumps. Artifacts in /pkg, local env files, and logs (server.log) are ignored by default.

🎨 Customising the Résumé

  • πŸ”— The public resume is https://cv.zqsdev.com/. The terminal uses this same canonical CV, in English and French.
  • 🧾 Edit the JSON files in static/data/ to refresh profile details, experiences, and skills for the interactive terminal and AI knowledge base.
  • πŸ“„ Edit static/cv/index.html (English), static/cv/fr.html (French) and the shared static/cv/resume.css for the public resume. The approved base V4 is available as resume.pdf in English and resume-fr.pdf in French. Each static page links to its matching PDF and the other language, including without JavaScript. resume.js localizes the clipboard message, preserves terminal return context when switching language and fits the document inside the original PDF frame.

🚒 Deployment

The server is optional at runtime; the public site is served from the static bundle.

☁️ Netlify (www.zqsdev.com & zqsdev.com)

  • 🌐 netlify.toml serves the HTML resume at cv.zqsdev.com; founding.zqsdev.com, devops.zqsdev.com, software.zqsdev.com and their old PDF links redirect to it. calendly.zqsdev.com still forwards to Calendly. Keep the legacy domain aliases so existing shared links continue to work.
  • πŸ” /api/* requests proxy through Netlify to https://api.zqsdev.com/api/:splat, keeping browser requests same-origin while hitting the Axum backend.
  • πŸ” Install the Netlify CLI (npm install -g netlify-cli) and authenticate once with netlify login or NETLIFY_AUTH_TOKEN.
  • πŸš€ make deploy-preview β†’ runs make build then netlify deploy --dir static --config netlify.toml.
  • πŸ” make deploy-prod β†’ same flow with --prod. Pass extra flags via NETLIFY_FLAGS (e.g. NETLIFY_FLAGS="--alias staging").
  • 🧭 In Netlify, add the custom domains founding.zqsdev.com, devops.zqsdev.com, and software.zqsdev.com, then create the matching DNS records before production validation.

🏑 Self-hosting (optional)

  1. πŸ› οΈ Run make build.
  2. πŸ“€ Publish the contents of static/ (including static/pkg/) to your CDN or object store.

If you want AI Mode in production, deploy the proxy (e.g. on Fly.io, Railway, or a small VPS) with:

  • πŸ”‘ OPENAI_API_KEY set.
  • βš™οΈ Optional HOST, PORT, and STATIC_DIR overrides.

The proxy reads static/data/*.json at startup, forwards questions to gpt-5.6-luna, and enforces spend ceilings before gracefully falling back to the classic terminal experience when limits trigger.

🧭 Systemd service (production)

  • 🧾 Unit file: /etc/systemd/system/zqs-terminal.service runs /opt/zqsdev/bin/zqs-terminal-server as the zqsdev user with WorkingDirectory=/opt/zqsdev.
  • 🌑️ Environment lives in /etc/zqsdev/server.env, including HOST=0.0.0.0, PORT=8787, STATIC_DIR=/opt/zqsdev/static, and the API keys used at runtime.
  • πŸ›ŽοΈ Manage the service with sudo systemctl status|restart zqs-terminal.service; logs stream to /opt/zqsdev/backend.log (mirrored here as ./backend.log) and via journalctl -u zqs-terminal.service.
  • πŸ“‘ Run make backend-log to tail the rolling log from the repository root.
  • πŸ” Public ingress: api.zqsdev.com terminates TLS with Nginx (config at /etc/nginx/sites-enabled/api.zqsdev.com) and proxies to the Axum service on 127.0.0.1:8787.
  • The binary listens on port 8787/tcp (/api/ai) and restarts automatically on failure.

Built with πŸ¦€ Rust and ❀️ by Alexandre DO-O ALMEIDA (ZQSDev). Enjoy the terminal! πŸ™‚

Public CV assets

The V4 content is ordinary semantic HTML, in English and French; each language has a matching one-page PDF. These are translations of the same CV, not different role variants. The original dark shell, rounded toolbar buttons and .page frame are preserved. On narrow screens the HTML reflows for reading, while printing preserves the A4 layout. Run python3 -m unittest scripts.test_cv_site to check the static CV and routing contracts.

Portrait: final 1254x1254 PNG supplied by Alexandre on 2026-09-08, published without further editing. The HTML and PDF use the same image. Studi logo: Studi, Wikimedia Commons, CC BY 4.0, unmodified. PlayStation symbol: official PlayStation site. YC badge: typographic Y. VibeRank icon: official SVG, copied locally on 2026-09-08; links to Aleqsd's profile.

Toolbar: monochrome GitHub and LinkedIn SVG marks inherit the light text color to stay legible on the dark background. Language flags are decorative SVGs with visible language names.

About

My resume website :)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages