spb/spboucher.ai Public
spboucher.ai — personal website of Simon-Pierre Boucher.
TypeScript 93.6%
HTML 5.4%
CSS 0.9%
1<!--2 README.md3 spboucher.ai Web4 Author: Simon-Pierre Boucher5 Mail: contact@spboucher.ai6-->78<div align="center">910# 🎓 spboucher.ai1112### Personal website of **Simon-Pierre Boucher**1314*Financial econometrics researcher and macOS/AI developer.*1516Professor — Department of Administrative Sciences, Université du Québec en Outaouais (UQO)1718<br/>1920[](https://www.spboucher.ai)21[](https://nextjs.org)22[](https://react.dev)23[](https://www.typescriptlang.org)2425[](https://tailwindcss.com)26[](https://ui.shadcn.com)27[](https://www.framer.com/motion/)28[](https://pm2.keymetrics.io)29[](https://ngrok.com)30[](https://uqo.ca)3132<br/>3334**[🏠 Home](https://www.spboucher.ai)** ·35**[🔬 Research](https://www.spboucher.ai/research)** ·36**[📚 Teaching](https://www.spboucher.ai/teaching)** ·37**[🖥️ Apps](https://www.spboucher.ai/apps)** ·38**[📄 CV](https://www.spboucher.ai/cv)**3940</div>4142---4344## 👋 About4546This repository powers **[www.spboucher.ai](https://www.spboucher.ai)** — the personal academic and developer website of Simon-Pierre Boucher. It presents his academic profile (research in financial econometrics, commodity markets, monetary policy announcements, high-frequency finance, volatility modelling, textual analysis, and financialization) alongside the **Zyquo suite**: six native macOS applications focused on AI and local LLMs.4748## ✨ Features4950- ⚡ **Next.js 16 App Router** — server components everywhere, static prerendering on every page51- 🎨 **Tailwind CSS v4 + shadcn/ui-style components** — clean academic aesthetic with a modern developer edge52- 🌗 **Dark mode** — system-aware with a manual toggle, no flash on load53- 🎬 **Framer Motion** — subtle scroll reveals, with `prefers-reduced-motion` and no-JS fallbacks54- 📱 **Fully responsive** — mobile-first, 1/2/3-column app grid55- ♿ **Accessible** — semantic HTML, alt text on all app icons, keyboard-friendly nav56- 💚 **Health endpoint** — `GET /api/health` for uptime monitoring5758## 🗺️ Site Map5960| Route | Content |61|-------|---------|62| `/` | Hero, bio, education, research highlight, technical skills |63| `/research` | Publications, working papers, conference presentations |64| `/teaching` | Courses taught (lecturer & teaching assistant, Université Laval) |65| `/apps` | Zyquo macOS app portfolio |66| `/cv` | CV summary + contact |67| `/api/health` | JSON health check |6869## 🖥️ The Zyquo macOS Suite7071Six native macOS applications for AI and local LLMs — Swift/SwiftUI, built for Apple Silicon.7273| | App | Description | Links |74|---|-----|-------------|-------|75| <img src="public/icons/zyquo-cloud.png" width="48" alt="Zyquo Cloud icon"/> | **☁️ Zyquo Cloud** | Multi-provider AI chat — Anthropic, OpenAI, and more in one unified interface | [Repo](https://git.spboucher.ai/zyquo-cloud) · [Release](https://git.spboucher.ai/zyquo-cloud/releases/tag/v1.0.0) · [DMG](https://git.spboucher.ai/zyquo-cloud/releases/latest/download/ZyquoCloud.dmg) |76| <img src="public/icons/zyquo-local.png" width="48" alt="Zyquo Local icon"/> | **💻 Zyquo Local** | 100% local LLMs with Apple MLX — private, offline, no API keys | [Repo](https://git.spboucher.ai/zyquo-local) · [Release](https://git.spboucher.ai/zyquo-local/releases/tag/v1.0.0) · [DMG](https://git.spboucher.ai/zyquo-local/releases/latest/download/ZyquoLocal.dmg) |77| <img src="public/icons/zyquo-agent.png" width="48" alt="Zyquo Agent icon"/> | **🤖 Zyquo Agent** | Autonomous AI agent for the Mac — tool calling, automation, multi-step workflows | [Repo](https://git.spboucher.ai/zyquo-agent) · [Release](https://git.spboucher.ai/zyquo-agent/releases/tag/v1.0.0) · [DMG](https://git.spboucher.ai/zyquo-agent/releases/latest/download/ZyquoAgent.dmg) |78| <img src="public/icons/zyquo-atlas.png" width="48" alt="Zyquo Atlas icon"/> | **🌍 Zyquo Atlas** | AI-native web browser — page understanding, summarization, assisted browsing | [Repo](https://git.spboucher.ai/zyquo-atlas) · [Release](https://git.spboucher.ai/zyquo-atlas/releases/tag/v1.0.0) · [DMG](https://git.spboucher.ai/zyquo-atlas/releases/latest/download/ZyquoAtlas.dmg) |79| <img src="public/icons/zyquo-mlx.png" width="48" alt="Zyquo MLX icon"/> | **⚒️ Zyquo MLX** | On-device model forge — LoRA/QLoRA fine-tuning, quantization, model management | [Repo](https://git.spboucher.ai/zyquo-mlx) · [Release](https://git.spboucher.ai/zyquo-mlx/releases/tag/v1.0.0) · [DMG](https://git.spboucher.ai/zyquo-mlx/releases/latest/download/ZyquoMLX.dmg) |80| <img src="public/icons/zyquo-router.png" width="48" alt="Zyquo Router icon"/> | **🔀 Zyquo Router** | Local LLM gateway — one unified endpoint across providers and local models | [Repo](https://git.spboucher.ai/zyquo-router) · [Release](https://git.spboucher.ai/zyquo-router/releases/tag/v1.0.0) · [DMG](https://git.spboucher.ai/zyquo-router/releases/latest/download/ZyquoRouter.dmg) |8182## 🚀 Quick Start8384```bash85git clone https://git.spboucher.ai/spboucher.ai.git86cd spboucher.ai8788npm install # install dependencies89npm run dev # local dev server → http://localhost:300090npm run build # production build91npm run start # serve production build92npm run typecheck # TypeScript check93```9495## 🌐 Production Deployment (node m2u64)9697The site runs on cluster node `m2u64` and is exposed publicly with **ngrok** bound to the custom domain. On m2u64 the app listens on **port 3100** (port 3000 is already in use on that node); both the app and the tunnel run under **PM2** for auto-restart.9899```mermaid100flowchart LR101 A["🌍 Visitor"] --> B["🔒 ngrok edge<br/>www.spboucher.ai"]102 B --> C["🖥️ m2u64 : 3100<br/>next start (PM2: spboucher)"]103 C --> D["💚 /api/health"]104```105106```bash107# on m2u64108npm ci && npm run build109pm2 start scripts/start-production.sh --name spboucher --interpreter /bin/zsh110pm2 start "ngrok http --url=www.spboucher.ai 3100" --name spboucher-ngrok111pm2 save112```113114- Always serve the production build (`npm run build && npm run start`) behind ngrok — never the dev server.115- If the tunnel drops, restart it: `pm2 restart spboucher-ngrok` (or run `ngrok http --url=www.spboucher.ai 3100` manually).116- Health check: `GET /api/health` → `{"status":"ok","service":"spboucher-ai"}`.117118## 📁 Project Structure119120```121app/122├── layout.tsx Root layout (theme init, header, footer)123├── page.tsx Home — hero, bio, education, highlight, skills124├── research/page.tsx Publications, working papers, presentations125├── teaching/page.tsx Courses taught126├── apps/page.tsx Zyquo macOS app portfolio127├── cv/page.tsx CV summary + contact128├── api/health/route.ts Health check endpoint129└── globals.css Tailwind v4 theme tokens (light/dark)130131components/132├── site-header.tsx Sticky nav + mobile menu133├── site-footer.tsx Footer134├── theme-toggle.tsx Dark mode toggle135├── reveal.tsx Framer Motion scroll reveal136├── app-card.tsx Zyquo app card (icon, description, 3 links)137└── ui/ shadcn/ui-style primitives (button, card, badge)138139lib/140├── apps.ts Zyquo suite data (single source of truth)141└── utils.ts cn() class merger142143public/icons/ Zyquo app icons (fetched from the app repos)144scripts/ Production start script (PM2)145```146147## 📐 Conventions148149- 📝 Every source file starts with the mandatory project header comment (see `CLAUDE.md`)150- 🇬🇧 All site content is in English151- 🔗 App download links on `/apps` (Repo / Release / DMG) must remain exactly as specified in `CLAUDE.md`152- 🧩 Server components by default; client components only where interactivity requires it153154## 📫 Contact155156| | |157|---|---|158| 🎓 Academic | [simon-pierre.boucher@uqo.ca](mailto:simon-pierre.boucher@uqo.ca) |159| ✉️ Personal | [contact@spboucher.ai](mailto:contact@spboucher.ai) |160| 🐙 GitHub | [@spboucher-ai](https://git.spboucher.ai) |161| 📍 Office | UQO, Gatineau — Pavillon Alexandre-Taché |162163---164165<div align="center">166167**© Simon-Pierre Boucher** — Université du Québec en Outaouais (UQO)168169*Built with Next.js · Tailwind CSS · shadcn/ui · Framer Motion — served from a Mac, tunneled to the world.* 🚇170171</div>172