SPB Git

spb/spboucher.ai Public

spboucher.ai — personal website of Simon-Pierre Boucher.

TypeScript 93.4% HTML 5.5% CSS 1%
12.3 KB · 369 lines tsx
Raw Blame History
1/*2  page.tsx3  spboucher.ai Web4  Author: Simon-Pierre Boucher5  Mail: contact@spboucher.ai6*/78import Image from "next/image";9import Link from "next/link";10import {11  AppWindow,12  ArrowRight,13  BookOpenCheck,14  Github,15  GraduationCap,16  Mail,17  MapPin,18  ScrollText,19  Sparkles,20  UserRound,21  Wrench,22} from "lucide-react";2324import { Badge } from "@/components/ui/badge";25import { buttonVariants } from "@/components/ui/button";26import {27  Card,28  CardContent,29  CardDescription,30  CardHeader,31  CardTitle,32} from "@/components/ui/card";33import { IconTile } from "@/components/icon-tile";34import { Reveal } from "@/components/reveal";35import { SectionHeading } from "@/components/section-heading";36import { cn } from "@/lib/utils";3738const stats = [39  { icon: BookOpenCheck, value: "1", label: "Peer-reviewed publication" },40  { icon: ScrollText, value: "10", label: "Working papers" },41  { icon: AppWindow, value: "9", label: "Native macOS apps" },42  { icon: Github, value: "30+", label: "Open-source repositories" },43];4445const education = [46  {47    degree: "Ph.D. in Business Administration (Finance and Insurance)",48    school: "Université Laval",49    period: "2020–Present",50  },51  {52    degree: "M.Sc. in Business Administration (Finance)",53    school: "Université Laval",54    period: "2017–2019",55    note: "Thesis: Impact of Commuting Times on Residential Property Values: Evidence from the Province of Québec",56  },57  {58    degree: "B.B.A. in Business Administration (Finance)",59    school: "Université Laval",60    period: "2013–2017",61  },62];6364const skillGroups = [65  {66    title: "Languages & frameworks",67    skills: [68      "Python",69      "TypeScript/JavaScript",70      "R",71      "MATLAB",72      "SAS/STATA",73      "SQL",74      "Julia",75      "C++",76      "Swift/SwiftUI",77      "LaTeX",78      "React/Next.js",79      "Node.js",80      "FastAPI",81      "Flask",82      "Streamlit",83      "Tailwind CSS",84      "shadcn/ui",85      "Framer Motion",86    ],87  },88  {89    title: "Data & econometrics",90    skills: [91      "Pandas",92      "NumPy",93      "statsmodels",94      "scikit-learn",95      "VAR",96      "BVAR",97      "HAR",98      "GARCH",99      "DCC-GARCH",100      "Event studies",101      "High-frequency analysis",102      "Realized volatility",103      "FRED",104      "FMP",105      "EODHD",106      "Yahoo Finance",107      "World Bank",108      "IMF",109      "OECD",110    ],111  },112  {113    title: "AI, LLMs & agents",114    skills: [115      "Claude/Anthropic SDK",116      "OpenAI API",117      "OpenRouter",118      "Vercel AI SDK",119      "Ollama",120      "llama.cpp",121      "GGUF",122      "Hugging Face",123      "Embeddings",124      "RAG",125      "Vector databases",126      "Tool-augmented agents",127      "LoRA",128      "QLoRA",129      "SFT fine-tuning",130    ],131  },132];133134export default function HomePage() {135  return (136    <div className="mx-auto max-w-5xl px-4 sm:px-6">137      {/* Hero */}138      <section className="relative py-16 sm:py-24">139        <div className="grid items-center gap-12 lg:grid-cols-[1fr_auto]">140          <Reveal>141            <p className="flex items-center gap-3 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-primary">142              <span aria-hidden="true" className="h-px w-8 bg-primary/60" />143              Professor · Dept. of Administrative Sciences · UQO144            </p>145            <h1 className="mt-5 font-display text-[2.75rem] font-semibold leading-[1.05] tracking-tight sm:text-7xl">146              Simon-Pierre147              <br />148              Boucher149            </h1>150            <p className="mt-6 max-w-2xl text-lg text-muted-foreground sm:text-xl">151              Financial econometrics researcher and{" "}152              <em className="font-display font-medium not-italic text-foreground [font-style:italic]">153                macOS/AI developer154              </em>155              .156            </p>157            <p className="mt-3 inline-flex items-start gap-2 text-sm text-muted-foreground">158              <MapPin159                className="mt-0.5 h-4 w-4 shrink-0 text-primary/70"160                aria-hidden="true"161              />162              Université du Québec en Outaouais (UQO), Gatineau — Pavillon163              Alexandre-Taché · Bilingual — French and English164            </p>165            <div className="mt-8 flex flex-wrap gap-3">166              <Link href="/research" className={cn(buttonVariants())}>167                View Research168                <ArrowRight aria-hidden="true" />169              </Link>170              <Link171                href="/apps"172                className={cn(buttonVariants({ variant: "secondary" }))}173              >174                Apps &amp; Open Source175              </Link>176              <a177                href="https://git.spboucher.ai"178                target="_blank"179                rel="noopener noreferrer"180                className={cn(buttonVariants({ variant: "outline" }))}181              >182                <Github aria-hidden="true" />183                GitHub184              </a>185            </div>186            <div className="mt-6 flex flex-col gap-1 text-sm text-muted-foreground sm:flex-row sm:gap-6">187              <a188                href="mailto:simon-pierre.boucher@uqo.ca"189                className="inline-flex items-center gap-2 transition-colors hover:text-foreground"190              >191                <Mail className="h-4 w-4" aria-hidden="true" />192                simon-pierre.boucher@uqo.ca193              </a>194              <a195                href="mailto:contact@spboucher.ai"196                className="inline-flex items-center gap-2 transition-colors hover:text-foreground"197              >198                <Mail className="h-4 w-4" aria-hidden="true" />199                contact@spboucher.ai200              </a>201            </div>202          </Reveal>203204          {/* Portrait — mounted like a plate in a monograph */}205          <Reveal delay={0.12} className="mx-auto w-60 sm:w-72 lg:w-80">206            <figure>207              <div className="relative">208                <div209                  aria-hidden="true"210                  className="absolute -bottom-2.5 -right-2.5 h-full w-full border border-primary/25 bg-[image:linear-gradient(to_right,oklch(0.44_0.155_268_/_10%)_1px,transparent_1px),linear-gradient(to_bottom,oklch(0.44_0.155_268_/_10%)_1px,transparent_1px)] bg-[size:8px_8px]"211                />212                <div className="relative border border-foreground/80 bg-card p-1.5 shadow-[var(--shadow-lift)]">213                  <Image214                    src="/profile/simon-pierre-boucher.jpeg"215                    alt="Portrait of Simon-Pierre Boucher"216                    width={880}217                    height={856}218                    priority219                    className="aspect-[5/6] w-full object-cover object-top"220                  />221                </div>222              </div>223              <figcaption className="mt-4 flex items-baseline justify-between font-mono text-[0.66rem] uppercase tracking-[0.14em] text-muted-foreground">224                <span>Fig. 1 — S.-P. Boucher</span>225                <span>Gatineau, QC</span>226              </figcaption>227            </figure>228          </Reveal>229        </div>230231        {/* Stats — annual-report rules */}232        <Reveal delay={0.15} className="mt-16">233          <div className="grid grid-cols-2 gap-x-8 gap-y-8 lg:grid-cols-4">234            {stats.map((stat, i) => (235              <div key={stat.label} className="border-t-2 border-foreground pt-3">236                <p className="font-mono text-[0.62rem] uppercase tracking-[0.18em] text-muted-foreground/70">237                  {String(i + 1).padStart(2, "0")}238                </p>239                <p className="mt-1 font-display text-4xl font-semibold tracking-tight">240                  {stat.value}241                </p>242                <p className="mt-1.5 font-mono text-[0.68rem] uppercase leading-relaxed tracking-[0.12em] text-muted-foreground">243                  {stat.label}244                </p>245              </div>246            ))}247          </div>248        </Reveal>249      </section>250251      {/* About */}252      <section className="border-t border-border/50 py-16 sm:py-20">253        <Reveal>254          <SectionHeading eyebrow="Profile" title="About" icon={UserRound} />255          <p className="mt-4 max-w-3xl leading-relaxed text-muted-foreground">256            Simon-Pierre Boucher is a Professor in the Department of257            Administrative Sciences at Université du Québec en Outaouais (UQO).258            His research focuses on financial econometrics, commodity markets,259            monetary policy announcements, high-frequency finance, volatility260            modelling, textual analysis, and financialization. He is completing261            a Ph.D. in Business Administration (Finance and Insurance) at262            Université Laval under the supervision of Prof. Marie-Hélène Gagnon263            and Prof. Gabriel Power. Alongside his academic work, he builds264            native macOS applications focused on AI and local LLMs (the Zyquo265            suite).266          </p>267        </Reveal>268      </section>269270      {/* Education */}271      <section className="border-t border-border/50 py-16 sm:py-20">272        <Reveal>273          <SectionHeading274            eyebrow="Background"275            title="Education"276            icon={GraduationCap}277          />278        </Reveal>279        <div className="mt-6 grid gap-4 sm:grid-cols-3">280          {education.map((item, i) => (281            <Reveal key={item.degree} delay={i * 0.08}>282              <Card className="h-full hover:-translate-y-1 hover:shadow-[var(--shadow-lift)]">283                <CardHeader>284                  <IconTile icon={GraduationCap} size="sm" className="mb-1" />285                  <CardTitle className="text-base leading-snug">286                    {item.degree}287                  </CardTitle>288                  <CardDescription>289                    {item.school} · {item.period}290                  </CardDescription>291                </CardHeader>292                {item.note && (293                  <CardContent>294                    <p className="text-sm italic text-muted-foreground">295                      {item.note}296                    </p>297                  </CardContent>298                )}299              </Card>300            </Reveal>301          ))}302        </div>303      </section>304305      {/* Research highlight */}306      <section className="border-t border-border/50 py-16 sm:py-20">307        <Reveal>308          <SectionHeading309            eyebrow="Latest"310            title="Research Highlight"311            icon={BookOpenCheck}312          />313          <Card className="mt-6">314            <CardHeader>315              <Badge className="w-fit">Publication · 2025</Badge>316              <CardTitle className="text-lg leading-snug">317                Speculative Trading in Energy Markets: Evidence from318                Macroeconomic Surprises319              </CardTitle>320              <CardDescription>321                Boucher, S.-P., Gagnon, M.-H., &amp; Power, G. J. —{" "}322                <em>The Energy Journal</em>323              </CardDescription>324            </CardHeader>325            <CardContent>326              <Link327                href="/research"328                className="inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline"329              >330                All publications, working papers &amp; presentations331                <ArrowRight className="h-4 w-4" aria-hidden="true" />332              </Link>333            </CardContent>334          </Card>335        </Reveal>336      </section>337338      {/* Skills */}339      <section className="border-t border-border/50 py-16 sm:py-20">340        <Reveal>341          <SectionHeading342            eyebrow="Toolbox"343            title="Technical Skills"344            icon={Wrench}345          />346        </Reveal>347        <div className="mt-6 grid gap-4 md:grid-cols-3">348          {skillGroups.map((group, i) => (349            <Reveal key={group.title} delay={i * 0.08}>350              <Card className="h-full">351                <CardHeader>352                  <CardTitle className="text-base">{group.title}</CardTitle>353                </CardHeader>354                <CardContent className="flex flex-wrap gap-1.5">355                  {group.skills.map((skill) => (356                    <Badge key={skill} variant="secondary">357                      {skill}358                    </Badge>359                  ))}360                </CardContent>361              </Card>362            </Reveal>363          ))}364        </div>365      </section>366    </div>367  );368}369