Initial commit: Migrate ReFL website to AstroJS
- Migrate from Hugo to AstroJS using Stargarden template - Add homepage, members, meetings, and resources pages - Configure Tailwind CSS with DaisyUI - Set up Inter font and custom primary color - Add Google Analytics integration
|
|
@ -0,0 +1,31 @@
|
|||
# build output
|
||||
dist/
|
||||
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
playwright-report/
|
||||
test-results/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
||||
# jetbrains setting folder
|
||||
.idea/
|
||||
|
||||
# obsidian workspace settings
|
||||
.obsidian/
|
||||
|
||||
.vscode/
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Agent Guidelines
|
||||
|
||||
## General
|
||||
- **Always use Conventional Commits** format.
|
||||
- **Always use Vitest v3** for testing React components.
|
||||
- **Always use JSDoc** style comments to document functions and types thoroughly.
|
||||
- **Always use functional components** in React.
|
||||
- **Prefer Generics in TypeScript** to avoid the `any` type, where pragmatic.
|
||||
- **Leverage the latest features** of React 19.x
|
||||
- **Use TailwindCSS v4** and **DaisyUI v5** when styling your frontend components.
|
||||
- **Always provide completed, functioning code**—avoid partial commits that break builds.
|
||||
- **Always use Markdown** for posts.
|
||||
- **Use existing patterns** in the codebase when implementing new features unless otherwise specified.
|
||||
- **Always use GH CLI** for GitHub operations, otherwise ask to perform alternatives.
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 Moxiebytes LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# ReFL - Reflexions sur les Fondements de la Logique
|
||||
|
||||
French scientific network on the foundations of logic and computation.
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
- Website: https://refl.fr
|
||||
- Zulip Chat: https://chat.refl.fr
|
||||
- Mailing list: refl@framalistes.org
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// @ts-check
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
|
||||
import react from '@astrojs/react';
|
||||
|
||||
import astroExpressiveCode from 'astro-expressive-code'
|
||||
|
||||
import pagefind from "astro-pagefind";
|
||||
|
||||
|
||||
const expressiveCode = astroExpressiveCode({
|
||||
// You can set configuration options here
|
||||
themes: ['github-dark'],
|
||||
styleOverrides: {
|
||||
// You can also override styles
|
||||
borderRadius: '0.5rem',
|
||||
frames: {
|
||||
shadowColor: '#124',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'https://refl.fr',
|
||||
vite: {
|
||||
plugins: [tailwindcss()],
|
||||
server: {
|
||||
watch: {
|
||||
usePolling: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
integrations: [sitemap(), react(), pagefind(),
|
||||
expressiveCode]
|
||||
});
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "refl-fr",
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro",
|
||||
"test": "vitest",
|
||||
"test:e2e": "playwright test",
|
||||
"test:ci": "npm run build && playwright test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/react": "^4.2.7",
|
||||
"@astrojs/sitemap": "^3.3.1",
|
||||
"@heroicons/react": "^2.2.0",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"astro": "^5.7.8",
|
||||
"astro-expressive-code": "^0.41.2",
|
||||
"astro-pagefind": "^1.8.3",
|
||||
"astro-seo": "^0.8.4",
|
||||
"daisyui": "^5.0.28",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"tailwindcss": "^4.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@playwright/test": "^1.56.1",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@types/react": "^19.1.3",
|
||||
"@types/react-dom": "^19.1.3",
|
||||
"jsdom": "^27.1.0",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^4.0.6"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 678 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 3.4 MiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 678 KiB |
|
|
@ -0,0 +1,68 @@
|
|||
<footer
|
||||
class="footer footer-horizontal footer-center bg-base-200 text-base-content rounded p-10"
|
||||
>
|
||||
<nav class="grid grid-flow-col gap-4">
|
||||
<a href="/members/" class="link link-hover">Members</a>
|
||||
<a href="/meetings/" class="link link-hover">Meetings</a>
|
||||
<a href="/resources/" class="link link-hover">Resources</a>
|
||||
</nav>
|
||||
<nav>
|
||||
<div class="grid grid-flow-col gap-4">
|
||||
<!-- Zulip Chat -->
|
||||
<a
|
||||
href="https://refl.zulipchat.com/"
|
||||
aria-label="ReFL Zulip Chat"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="flex items-center gap-1"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
class="fill-current"
|
||||
>
|
||||
<path
|
||||
d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z" />
|
||||
</svg>
|
||||
</a>
|
||||
<!-- Email icon link -->
|
||||
<a
|
||||
href="mailto:refl@framalistes.org"
|
||||
aria-label="Email ReFL"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
class="fill-current"
|
||||
>
|
||||
<g
|
||||
stroke-linejoin="round"
|
||||
stroke-linecap="round"
|
||||
stroke-width="2"
|
||||
fill="none"
|
||||
>
|
||||
<rect
|
||||
width="20"
|
||||
height="16"
|
||||
x="2"
|
||||
y="4"
|
||||
rx="2"
|
||||
stroke="currentColor" />
|
||||
<path
|
||||
d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"
|
||||
stroke="currentColor" />
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<aside>
|
||||
<p>
|
||||
ReFL - Reflexions sur les Fondements de la Logique
|
||||
</p>
|
||||
</aside>
|
||||
</footer>
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
import { Bars3Icon } from "@heroicons/react/24/outline";
|
||||
import ThemeToggle from '../components/ThemeToggle.astro';
|
||||
---
|
||||
|
||||
<header class="shadow-sm bg-base-100">
|
||||
<!-- ********** Mobile (< lg): drawer & navbar ********** -->
|
||||
<div class="drawer lg:hidden">
|
||||
<!-- Hidden checkbox toggles the drawer -->
|
||||
<input id="nav-drawer" type="checkbox" class="drawer-toggle" />
|
||||
|
||||
<div class="drawer-content flex flex-col">
|
||||
<nav class="navbar bg-base-100 w-full lg:px-4 relative px-2">
|
||||
<!-- Hamburger icon on the left -->
|
||||
<div class="flex-none">
|
||||
<label
|
||||
for="nav-drawer"
|
||||
aria-label="Open sidebar"
|
||||
class="btn btn-ghost btn-square"
|
||||
>
|
||||
<Bars3Icon className="h-5 w-5" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Logo centered absolutely -->
|
||||
<a
|
||||
href="/"
|
||||
class="absolute left-1/2 -translate-x-1/2 flex items-center"
|
||||
>
|
||||
<span class="text-2xl font-bold">ReFL</span>
|
||||
</a>
|
||||
<div class="flex-none ml-auto">
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Slide-out sidebar -->
|
||||
<div class="drawer-side">
|
||||
<label for="nav-drawer" class="drawer-overlay" aria-label="Close sidebar"
|
||||
></label>
|
||||
<ul class="menu p-4 w-80 bg-base-100 min-h-full">
|
||||
<li>
|
||||
<a href="/" class="normal-case font-bold text-xl">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/members/" class="normal-case font-bold text-xl">Members</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/meetings/" class="normal-case font-bold text-xl">Meetings</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/resources/" class="normal-case font-bold text-xl">Resources</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ********** Desktop (>= lg): standard navbar ********** -->
|
||||
<nav
|
||||
class="navbar hidden lg:flex w-full bg-base-100"
|
||||
style="--navbar-padding:0;"
|
||||
>
|
||||
<div class="navbar-start pl-6">
|
||||
<a href="/" class="flex items-center gap-2">
|
||||
<span class="text-2xl font-bold">ReFL</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-center">
|
||||
<ul class="menu menu-horizontal gap-2">
|
||||
<li>
|
||||
<a href="/" class="normal-case font-bold text-lg">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/members/" class="normal-case font-bold text-lg">Members</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/meetings/" class="normal-case font-bold text-lg">Meetings</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/resources/" class="normal-case font-bold text-lg">Resources</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="navbar-end">
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
/**
|
||||
* ThemeToggle component for DaisyUI theme switching.
|
||||
* Handles theme persistence, sync, and toggle UI for both mobile and desktop.
|
||||
* @component
|
||||
*/
|
||||
import { SunIcon, MoonIcon } from "@heroicons/react/24/outline";
|
||||
---
|
||||
<!-- Sync theme-controller checkboxes & persist selection -->
|
||||
<script>
|
||||
import "../scripts/themeController.ts";
|
||||
</script>
|
||||
<!-- DaisyUI theme toggle switch -->
|
||||
<label class="swap swap-rotate cursor-pointer lg:ml-2">
|
||||
<input type="checkbox" class="theme-controller" value="business" />
|
||||
<SunIcon className="swap-off h-6 w-6 lg:h-10 lg:w-10" />
|
||||
<MoonIcon className="swap-on h-6 w-6 lg:h-10 lg:w-10" />
|
||||
</label>
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// src/content/config.ts
|
||||
// No content collections defined - using static pages instead
|
||||
export const collections = {};
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
import "../styles/global.css";
|
||||
import Navbar from "../components/Navbar.astro";
|
||||
import Footer from "../components/Footer.astro";
|
||||
import logo from "../assets/logo.svg";
|
||||
|
||||
import { SEO } from "astro-seo";
|
||||
|
||||
export interface Props {
|
||||
/** Optional granular SEO overrides coming from .astro pages or components */
|
||||
seo?: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
};
|
||||
/** Standard front‑matter fields coming from Markdown/MDX pages */
|
||||
title?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
// Destructure front‑matter fields as well as the existing `seo` object
|
||||
const { seo = {}, title, description } = Astro.props;
|
||||
|
||||
/** Merge explicit `seo` overrides with any front‑matter fields.
|
||||
* Values defined in `seo` win over front‑matter, preserving backward compatibility.
|
||||
*/
|
||||
const seoConfig = {
|
||||
...seo,
|
||||
title: seo.title ?? title,
|
||||
description: seo.description ?? description,
|
||||
};
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="business">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<!-- Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-7308Y1HGM9"></script>
|
||||
<script is:inline>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-7308Y1HGM9');
|
||||
</script>
|
||||
<!-- Persisted theme (dark / light) is applied as early as possible -->
|
||||
<script is:inline>
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme) {
|
||||
document.documentElement.setAttribute('data-theme', savedTheme);
|
||||
}
|
||||
</script>
|
||||
<SEO
|
||||
{...seoConfig}
|
||||
title={seoConfig.title}
|
||||
description={seoConfig.description ??
|
||||
"ReFL - Réflexions sur les Fondements de la Logique"}
|
||||
titleTemplate="%s – ReFL"
|
||||
titleDefault="ReFL"
|
||||
/>
|
||||
<slot name="head" />
|
||||
<script
|
||||
type="application/ld+json"
|
||||
set:html={JSON.stringify({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "ReFL",
|
||||
url: Astro.site,
|
||||
logo: new URL(logo.src, Astro.site).href,
|
||||
sameAs: ["https://refl.zulipchat.com/"],
|
||||
})}
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
</head>
|
||||
|
||||
<body
|
||||
class="bg-base-100 text-base-content min-h-screen flex flex-col overflow-x-hidden"
|
||||
>
|
||||
<Navbar />
|
||||
|
||||
<!-- Main page content -->
|
||||
<main class="flex-1 container mx-auto px-4 py-8">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
const { frontmatter } = Astro.props;
|
||||
---
|
||||
|
||||
<Layout seo={{ title: frontmatter.title, description: frontmatter.description }}>
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-bold mb-8">{frontmatter.title}</h1>
|
||||
<div class="prose prose-lg max-w-none">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import { Image } from "astro:assets";
|
||||
import notFound from "../assets/404.png";
|
||||
---
|
||||
|
||||
<Layout seo={{ title: "Page Not Found", description: "We couldn’t find that page." }}>
|
||||
<Fragment slot="head">
|
||||
<meta name="robots" content="noindex" />
|
||||
</Fragment>
|
||||
<section class="min-h-[60vh] flex items-center">
|
||||
<div class="container mx-auto px-4 w-full">
|
||||
<div class="card bg-base-200 shadow-xl max-w-3xl mx-auto">
|
||||
<figure class="p-6">
|
||||
<Image
|
||||
src={notFound}
|
||||
alt="Page not found"
|
||||
width={560}
|
||||
height={315}
|
||||
class="mx-auto my-8 rounded-lg shadow-md"
|
||||
loading="lazy"
|
||||
/>
|
||||
</figure>
|
||||
<div class="card-body items-center text-center">
|
||||
<h1 class="card-title text-3xl">Page not found</h1>
|
||||
<p class="text-base-content/70">The page you’re looking for doesn’t exist or has moved.</p>
|
||||
<div class="card-actions justify-center mt-2">
|
||||
<a href="/" class="btn btn-primary">Go home</a>
|
||||
<a href="/posts/" class="btn">View posts</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import { Image } from "astro:assets";
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<!-- Hero Section -->
|
||||
<section class="text-center py-12">
|
||||
<h1 class="text-6xl font-bold mb-4">ReFL</h1>
|
||||
<p class="text-xl text-base-content/70 mb-8">Reflexions sur les Fondements de la Logique</p>
|
||||
</section>
|
||||
|
||||
<!-- Description -->
|
||||
<section class="prose prose-lg mx-auto mb-12">
|
||||
<p>
|
||||
A French scientific network on the foundations of logic and computation. The group was initially founded by four PhD students during the "Linear Logic Winter School 2022", but we now aim for a broader community bringing together logicians, computer scientists, mathematicians, philosophers, and more. Our members come from various backgrounds, both from academia and industry, and share a taste for deep questions, with the aim of proposing original insights and new perspectives on the foundations of computation and logic. In particular, we take a great interest in the role of computer science in understanding logic.
|
||||
</p>
|
||||
<p>
|
||||
We are inspired by the transdisciplinarity of the LIGC working group, which gathered researchers from various fields around the foundations of (linear) logic.
|
||||
</p>
|
||||
<p>
|
||||
We use French for our discussions, seminars, and meetings, but we welcome English speakers as well.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Contact Links -->
|
||||
<section class="flex flex-wrap justify-center gap-4 mb-12">
|
||||
<a href="https://refl.zulipchat.com/" target="_blank" rel="noopener noreferrer" class="btn btn-primary">
|
||||
Zulip Chat
|
||||
</a>
|
||||
<a href="mailto:refl@framalistes.org" class="btn btn-outline">
|
||||
Mailing List
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<!-- Scientific Interests -->
|
||||
<section class="mb-12">
|
||||
<h2 class="text-2xl font-bold mb-6">Our Scientific Interests</h2>
|
||||
<ul class="list-disc list-inside space-y-2 text-base-content/80">
|
||||
<li>Foundations and philosophy of logic, computation and mathematics</li>
|
||||
<li>History of logic and computation</li>
|
||||
<li>Category theory and its applications</li>
|
||||
<li>Proof-program correspondence and proof/type theory</li>
|
||||
<li>Jean-Yves Girard's works: linear logic, proof-nets, ludics, geometry of interaction, transcendental syntax</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Activities -->
|
||||
<section class="mb-12">
|
||||
<h2 class="text-2xl font-bold mb-6">Our Activities</h2>
|
||||
<ul class="list-disc list-inside space-y-2 text-base-content/80">
|
||||
<li>Seminars (generally online)</li>
|
||||
<li>Debates and discussions on Zulip</li>
|
||||
<li>Private meetings in person between some participants</li>
|
||||
<li>Collaboration and mutual assistance (thesis, research, programming, ...)</li>
|
||||
<li>Writing, communication, programming projects</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Sponsors -->
|
||||
<section class="mb-12">
|
||||
<h2 class="text-2xl font-bold mb-6">Sponsors</h2>
|
||||
<div class="flex items-center gap-6">
|
||||
<a href="https://zulip.com/" target="_blank" rel="noopener noreferrer" class="shrink-0">
|
||||
<img src="/images/zulip.png" alt="Zulip" class="h-24 w-auto" />
|
||||
</a>
|
||||
<p class="text-base-content/80">
|
||||
Sponsored by Zulip. Zulip is an open-source modern team chat app designed to keep both live and asynchronous conversations organized.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</Layout>
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
|
||||
const meetings = [
|
||||
{
|
||||
title: "Meeting around Jean-Yves Girard",
|
||||
date: "Nov 23, 2025",
|
||||
people: 4
|
||||
},
|
||||
{
|
||||
title: "Meeting RI2025 in Morbihan",
|
||||
date: "April 28 – May 2, 2025",
|
||||
organizers: "Jérémy Hervé, Boris Eng, Victor Benitah",
|
||||
people: 16,
|
||||
link: "/refli2025/",
|
||||
linkText: "Details of the meeting"
|
||||
},
|
||||
{
|
||||
title: "Fondements esthétiques de la logique",
|
||||
date: "November 1, 2024",
|
||||
by: "Pierre Cardascia",
|
||||
people: 16,
|
||||
talks: [
|
||||
{
|
||||
title: "Morts du mythe, de l'art, de la philosophie, de la logique : Itinéraire d'un problème serial-killer",
|
||||
speaker: "Pierre Cardascia",
|
||||
duration: "1h30",
|
||||
slides: "/documents/cardascia-01-11-2024.pdf"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Introduction to transcendental syntax",
|
||||
date: "June 20, 2024",
|
||||
by: "Boris Eng and Pablo Donato",
|
||||
people: 5
|
||||
},
|
||||
{
|
||||
title: "Analytic and continental philosophy",
|
||||
date: "May 20, 2024",
|
||||
by: "Luc Pommeret",
|
||||
people: 17,
|
||||
talks: [
|
||||
{
|
||||
title: "Le professionnel et l'écrivain : le pouvoir offensif de la philosophie analytique",
|
||||
speaker: "Luc Pommeret",
|
||||
duration: "1h30"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Technical introduction to transcendental syntax",
|
||||
date: "May 11, 2024",
|
||||
people: 4,
|
||||
talks: [
|
||||
{ title: "Introduction to Peirce's philosophy", speaker: "Pablo Donato", duration: "30min" },
|
||||
{ title: "Stellar resolution and Girard's knitting", speaker: "Boris Eng" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Meeting around Jean-Yves Girard",
|
||||
date: "May 10, 2024",
|
||||
people: 5
|
||||
},
|
||||
{
|
||||
title: "Program verification",
|
||||
date: "June 26, 2023",
|
||||
by: "Xavier Denis",
|
||||
talks: [
|
||||
{ title: "Presentation of the Rust programming language", speaker: "Xavier Denis", duration: "1h" },
|
||||
{ title: "Why formal verification is getting it wrong", speaker: "Xavier Denis", duration: "1h" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Logic and quantum computation",
|
||||
date: "May 31, 2023",
|
||||
by: "Kostia Chardonnet",
|
||||
chair: "Kostia Chardonnet",
|
||||
talks: [
|
||||
{ title: "Quantum computation and Geometry of Interaction", speaker: "Kostia Chardonnet", duration: "45min" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Logic and Categories",
|
||||
date: "March 24, 2023",
|
||||
by: "Tito and Valentin Maestracci",
|
||||
chair: "Pablo Donato",
|
||||
talks: [
|
||||
{
|
||||
title: "Pourquoi les catégories sont la bonne façon de faire de la sémantique dénotationnelle",
|
||||
speaker: "Tito",
|
||||
duration: "1h",
|
||||
slides: "https://nguyentito.eu/2023-03-refl.pdf"
|
||||
},
|
||||
{ title: "Catégories monoïdales à trace", speaker: "Valentin Maestracci", duration: "1h" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "ReFL first seminar of the year",
|
||||
date: "February 21, 2023",
|
||||
by: "Pablo Donato, Davide Barbarossa, Adrien Ragot, Boris Eng, Sidney Congard",
|
||||
chair: "Boris Eng",
|
||||
people: 13,
|
||||
talks: [
|
||||
{ title: "Du calcul des séquents à la logique linéaire", speaker: "Pablo Donato", duration: "30min" },
|
||||
{ title: "Correspondance de Curry-Howard et théorie des types", speaker: "Davide Barbarossa", duration: "30min" },
|
||||
{ title: "Réseaux de preuve multiplicatifs avec règle daemon", speaker: "Adrien Ragot", duration: "30min" },
|
||||
{
|
||||
title: "Introduction à la géométrie de l'interaction originale de Girard",
|
||||
speaker: "Boris Eng",
|
||||
duration: "30min",
|
||||
slides: "https://engboris.fr/documents/slides_tc1_2023.pdf"
|
||||
},
|
||||
{ title: "Introduction à la syntaxe transcendantale", speaker: "Sidney Congard", duration: "30min" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Freedom and Control in Logic and Computation",
|
||||
date: "February 1, 2023",
|
||||
people: 4,
|
||||
talks: [
|
||||
{ title: "Apodictic and Epidictic in Girard's transcendental syntax. Control over computation (synchronicity, sequentiality, direction of computation)." }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Proof-nets and Deep Inference",
|
||||
date: "April 27, 2022",
|
||||
by: "Pablo Donato",
|
||||
people: 5,
|
||||
talks: [
|
||||
{ title: "Comparison between deep inference and proof-nets. Non-sequentialisable multiplicative connectives, ludics, proof assistants, sequent calculi as recipes for computational objects (constellations)." }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Computation and Meaning",
|
||||
date: "March 23, 2022",
|
||||
by: "Boris Eng",
|
||||
people: 8,
|
||||
talks: [
|
||||
{ title: "Discussion on stellar resolution and ways to put meaning on it (Girard's \"usine\" and \"usage\"), correctness criterion, realisability theory." }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Lambda-calculus and stellar resolution",
|
||||
date: "March 9, 2022",
|
||||
by: "Boris Eng and Julien Marquet",
|
||||
people: 6,
|
||||
talks: [
|
||||
{ title: "Discussion on possible encodings of lambda-calculus and Lafont's interaction nets with unification (by using stellar resolution). Decomposition of tests as constellations. Discussions on optimal reduction of lambda-calculus." }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Round table discussion at CIRM's \"Logic and Interaction\" thematic month",
|
||||
date: "February 2022",
|
||||
people: 8,
|
||||
talks: [
|
||||
{ title: "Discussions on Girard's transcendental syntax. Focus on Girard's \"conceptual knitting\"." }
|
||||
]
|
||||
}
|
||||
];
|
||||
---
|
||||
|
||||
<Layout seo={{ title: "Meetings", description: "ReFL seminars and meetings" }}>
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-bold mb-4">Meetings</h1>
|
||||
<p class="text-base-content/70 mb-8">Some meetings were private and informal. For these reasons, they are not recorded here.</p>
|
||||
|
||||
<div class="space-y-6">
|
||||
{meetings.map((meeting) => (
|
||||
<article class="border-l-4 border-primary pl-5 py-2">
|
||||
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1">
|
||||
<h2 class="text-xl font-semibold">{meeting.title}</h2>
|
||||
<span class="text-sm text-base-content/60">{meeting.date}</span>
|
||||
{meeting.people && <span class="badge badge-ghost badge-sm">{meeting.people} people</span>}
|
||||
</div>
|
||||
|
||||
{meeting.by && (
|
||||
<p class="text-sm text-base-content/70 mt-1">By {meeting.by}</p>
|
||||
)}
|
||||
|
||||
{meeting.organizers && (
|
||||
<p class="text-sm text-base-content/70 mt-1">Organized by {meeting.organizers}</p>
|
||||
)}
|
||||
|
||||
{meeting.chair && (
|
||||
<p class="text-sm text-base-content/70">Chair: {meeting.chair}</p>
|
||||
)}
|
||||
|
||||
{meeting.link && (
|
||||
<a href={meeting.link} class="text-primary hover:opacity-80 text-sm mt-2 inline-block">
|
||||
→ {meeting.linkText}
|
||||
</a>
|
||||
)}
|
||||
|
||||
{meeting.talks && meeting.talks.length > 0 && (
|
||||
<ul class="mt-3 space-y-2">
|
||||
{meeting.talks.map((talk) => (
|
||||
<li class="text-sm bg-base-200/50 border border-base-content/20 rounded-lg px-4 py-2">
|
||||
<div class="flex flex-wrap items-baseline gap-2">
|
||||
{talk.slides ? (
|
||||
<a href={talk.slides} target="_blank" rel="noopener noreferrer" class="text-primary hover:opacity-80">
|
||||
{talk.title}
|
||||
</a>
|
||||
) : (
|
||||
<span>{talk.title}</span>
|
||||
)}
|
||||
</div>
|
||||
{(talk.speaker || talk.duration) && (
|
||||
<div class="text-base-content/60 mt-1">
|
||||
{talk.speaker && <span>{talk.speaker}</span>}
|
||||
{talk.speaker && talk.duration && <span> · </span>}
|
||||
{talk.duration && <span>{talk.duration}</span>}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
|
||||
const cofounders = [
|
||||
{
|
||||
name: "Davide Barbarossa",
|
||||
url: "https://davidebarbarossa12.github.io/index.html",
|
||||
interests: "Lambda-calculus, type theory, linear logic, category theory, classical realizability, philosophy of mathematics",
|
||||
affiliation: "Università di Bologna"
|
||||
},
|
||||
{
|
||||
name: "Pablo Donato 🌸",
|
||||
url: "https://pablogician.refl.fr/",
|
||||
role: "administrator",
|
||||
interests: "Proof theory, type theory, topos theory, proof assistants, human-computer interaction, end-user programming",
|
||||
affiliation: "Grothendieck Institute"
|
||||
},
|
||||
{
|
||||
name: "Boris Eng 🦖",
|
||||
url: "https://engboris.refl.fr",
|
||||
roles: ["administrator", "coordinator"],
|
||||
interests: "Transcendental syntax, proof theory, linear logic",
|
||||
affiliation: "R&D engineer at OCamlPro"
|
||||
},
|
||||
{
|
||||
name: "Valentin Maestracci",
|
||||
url: "https://vmaestracci.github.io/",
|
||||
interests: "Lambda-calculus, type theory, homotopy type theory, Dedukti, directed homotopy theory, rewriting",
|
||||
affiliation: "Université Aix-Marseille"
|
||||
}
|
||||
];
|
||||
|
||||
const members = [
|
||||
{
|
||||
name: "Victor Benitah",
|
||||
interests: "Formal systems explorer, co-founder of an electronic firm",
|
||||
affiliation: "Airline pilot at Air France"
|
||||
},
|
||||
{
|
||||
name: "Hugo Cadière",
|
||||
url: "https://www.univ-lyon3.fr/m-hugo-cadiere",
|
||||
interests: "Philosophy of mathematics / computer science / language / mind, German Idealism and XXth century German philosophy",
|
||||
affiliation: "Université Jean-Moulin Lyon 3"
|
||||
},
|
||||
{
|
||||
name: "Pierre Cardascia 🎲",
|
||||
url: "https://suboptimal.games/",
|
||||
interests: "Philosophy, Game Design, Entrepreneurship, Immersive Experience, Poetry",
|
||||
affiliation: "SubOptimal Games"
|
||||
},
|
||||
{
|
||||
name: "Baptiste Chanus",
|
||||
interests: "Descriptive complexity",
|
||||
affiliation: "Université Paris 1 Panthéon-Sorbonne"
|
||||
},
|
||||
{
|
||||
name: "Kostia Chardonnet",
|
||||
url: "https://kostiachardonnet.github.io/",
|
||||
interests: "Computer science, quantum computation, cyclic proofs",
|
||||
affiliation: "Centre Inria de l'Université de Lorraine (MOCQUA)"
|
||||
},
|
||||
{
|
||||
name: "Sidney Congard",
|
||||
url: "https://dwarfobserver.github.io/",
|
||||
interests: "Semantics of programming languages",
|
||||
affiliation: "Centre Inria de l'Université de Rennes (Gallinette)"
|
||||
},
|
||||
{
|
||||
name: "Xavier Denis",
|
||||
url: "https://xav.io/",
|
||||
interests: "Deductive verification and specification of Rust programs",
|
||||
affiliation: ""
|
||||
},
|
||||
{
|
||||
name: "Pierre Benjamin Giraud",
|
||||
interests: "Multi-dimensional (Logic x Cubes & Rewriting systems x Automata), automata for proofs, philoTechny of mathematics",
|
||||
affiliation: "Centre Inria de l'Université de Rennes (Gallinette)"
|
||||
},
|
||||
{
|
||||
name: "Charles Grellois",
|
||||
url: "https://www.sheffield.ac.uk/cs/people/academic/charles-grellois",
|
||||
interests: "Semantics, (linear) logic, automata theory, higher-order model-checking, mathematical modeling, probabilistic termination",
|
||||
affiliation: "University of Sheffield"
|
||||
},
|
||||
{
|
||||
name: "Jérémy Hervé 🍄",
|
||||
role: "external communications",
|
||||
interests: "Mushrooms, operating systems design",
|
||||
affiliation: "Independent"
|
||||
},
|
||||
{
|
||||
name: "Ambroise Lafont",
|
||||
url: "https://amblafont.github.io/",
|
||||
interests: "Type Theory and Category Theory",
|
||||
affiliation: "École Polytechnique (LIX)"
|
||||
},
|
||||
{
|
||||
name: "Luc Pommeret",
|
||||
url: "https://lucpommeret.com/",
|
||||
interests: "Logic, LLM (Machine learning)",
|
||||
affiliation: "LISN Paris-Saclay"
|
||||
},
|
||||
{
|
||||
name: "Adrien Ragot",
|
||||
interests: "Proof-nets, interaction nets, implicit computational complexity, lambda-calculus, linear logic",
|
||||
affiliation: "Université Sorbonne Paris Nord / University Roma Tre"
|
||||
},
|
||||
{
|
||||
name: "Paul Séjourné",
|
||||
interests: "Archaic and contemporary philosophy (of mathematics), algebraic geometry, category theory",
|
||||
affiliation: "Université Paris-Sorbonne"
|
||||
},
|
||||
{
|
||||
name: "Vincent Moreau",
|
||||
url: "https://www.irif.fr/~moreau/",
|
||||
interests: "Category theory, type theory, denotational semantics, topology, algebra, proof assistants",
|
||||
affiliation: "Université Paris Cité (IRIF)"
|
||||
},
|
||||
{
|
||||
name: "François-René Rideau (Faré)",
|
||||
interests: "",
|
||||
affiliation: ""
|
||||
},
|
||||
{
|
||||
name: "Tito",
|
||||
url: "https://nguyentito.eu/",
|
||||
interests: "Links between linear logic and automata theory, combinatorics, computational complexity, algorithms",
|
||||
affiliation: "CNRS & Aix-Marseille"
|
||||
}
|
||||
];
|
||||
|
||||
const visitors = [
|
||||
"Titouan Carette", "Clémence Chanavat", "Bernardo Marques", "Julien Marquet",
|
||||
"Rémi Nollet", "Federico Olimpieri", "Raphaël Tossings", "Pierre Vial",
|
||||
"Quentin", "Gaël Deest", "Martin Tricaud", "Fadi Shawki", "Éliès Harington",
|
||||
"Axel Kerinec", "Aloÿs Dufour", "Bernardo", "Anne-Laure", "Escherichia",
|
||||
"Alexey", "Roman Perez", "Nico", "Chirine Laghjichi", "Jonty Male",
|
||||
"Alexis Toumi", "Baptiste Colin", "Léo", "Noé Ensarguet"
|
||||
];
|
||||
---
|
||||
|
||||
<Layout seo={{ title: "Members", description: "Members of the ReFL research network" }}>
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-bold mb-8">Members</h1>
|
||||
|
||||
<!-- Co-founders -->
|
||||
<section class="mb-10">
|
||||
<h2 class="text-2xl font-bold mb-4">Co-founders</h2>
|
||||
<ul class="space-y-4">
|
||||
{cofounders.map((person) => (
|
||||
<li class="border-l-2 border-primary pl-4">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
{person.url ? (
|
||||
<a href={person.url} target="_blank" rel="noopener noreferrer" class="font-semibold text-primary hover:opacity-80">
|
||||
{person.name}
|
||||
</a>
|
||||
) : <span class="font-semibold">{person.name}</span>}
|
||||
{person.affiliation && <span class="text-base-content/70">— {person.affiliation}</span>}
|
||||
{person.role && <span class="badge badge-primary badge-sm">{person.role}</span>}
|
||||
{person.roles && person.roles.map((r) => (
|
||||
<span class="badge badge-primary badge-sm">{r}</span>
|
||||
))}
|
||||
</div>
|
||||
{person.interests && <div class="text-sm text-base-content/80 mt-1">{person.interests}</div>}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Members -->
|
||||
<section class="mb-10">
|
||||
<h2 class="text-2xl font-bold mb-4">Members</h2>
|
||||
<ul class="space-y-4">
|
||||
{members.map((person) => (
|
||||
<li class="border-l-2 border-base-300 pl-4">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
{person.url ? (
|
||||
<a href={person.url} target="_blank" rel="noopener noreferrer" class="font-semibold text-primary hover:opacity-80">
|
||||
{person.name}
|
||||
</a>
|
||||
) : <span class="font-semibold">{person.name}</span>}
|
||||
{person.affiliation && <span class="text-base-content/70">— {person.affiliation}</span>}
|
||||
{person.role && <span class="badge badge-primary badge-sm">{person.role}</span>}
|
||||
</div>
|
||||
{person.interests && <div class="text-sm text-base-content/80 mt-1">{person.interests}</div>}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Visitors -->
|
||||
<section class="mb-10">
|
||||
<h2 class="text-2xl font-bold mb-4">Visitors and guests</h2>
|
||||
<p class="text-base-content/80">
|
||||
{visitors.join(", ")}.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</Layout>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
layout: ../layouts/Markdown.astro
|
||||
title: "ReFLi 2025 Meeting"
|
||||
description: "ReFLi 2025 retreat in Lizio, Morbihan"
|
||||
---
|
||||
|
||||
Rencontre du **28 avril 2025** au **2 mai 2025** a Lizio (Morbihan).
|
||||
|
||||
**Organisateurs :**
|
||||
- Victor Benitah
|
||||
- Boris Eng
|
||||
- Jeremy Herve
|
||||
|
||||
La rencontre est organisee par l'association _"Reflets Intemporels"_ fondee
|
||||
pour l'occasion.
|
||||
|
||||
Il s'agit d'une rencontre reunissant environ 16 personnes. Parmi ces
|
||||
participants, des membres et proches du reseau de recherche _ReFL_ et de la
|
||||
societe privee d'electronique _Crystal_.
|
||||
|
||||
Cette rencontre est l'occasion d'experimenter a la fois les capacites de ReFL et
|
||||
Crystal a organiser et des rencontres scientifiques mais aussi d'explorer des
|
||||
methodes differentes de communication et de collaboration. Les suggestions
|
||||
d'activites comprennent des sessions d'echanges cadres et quelques exposes
|
||||
tres courts.
|
||||
|
||||
La rencontre tournera autour des grands themes de la **verite**, de la
|
||||
**fiabilite** et de la notion de **systeme**, teinte d'ingenierie mais sans y
|
||||
etre limite.
|
||||
|
||||
**Autres sujets d'interet des participants :**
|
||||
- Fondements de la logique et des mathematiques
|
||||
- Epistemologie
|
||||
- Cybernetique et systemes complexes
|
||||
- Musique
|
||||
- Enseignement
|
||||
- Electronique
|
||||
- Conception des langages de programmation et des systemes d'exploitation
|
||||
- Fiabilite des systemes
|
||||
- Decentralisation (internet, blockchains, ...)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
layout: ../layouts/Markdown.astro
|
||||
title: "Resources"
|
||||
description: "Academic resources and references on logic and computation"
|
||||
---
|
||||
|
||||
- *"Le fantome de la transparence"* -- Jean-Yves Girard
|
||||
- [*Syntaxe transcendentale (Wikipedia)*](https://fr.wikipedia.org/wiki/Syntaxe_transcendantale)
|
||||
- [*Transcendental Syntax (nlab)*](https://ncatlab.org/nlab/show/transcendental+syntax)
|
||||
- [*"An exegesis of transcendental syntax" (PhD thesis)* -- Boris Eng](https://hal.science/tel-04179276v1)
|
||||
- [*"La logique face a l'arbitraire" (French)* -- Sidney Congard](https://hal.science/hal-03689001/document)
|
||||
- [*"Les limites de la correspondance preuve/programme" (French)* -- Laurent Regnier](https://www.i2m.univ-amu.fr/perso/laurent.regnier/articles/ch.pdf)
|
||||
- [*"Aristote et l'electricien : le branchement des idees" (French video)* -- Paolo Pistone](https://vimeo.com/167115532)
|
||||
- [*"D'une logique a l'autre" (French video)* -- Laurent Regnier](https://vimeo.com/314743657)
|
||||
- [*"Symmetry and interactivity in Programming"* -- Pierre-Louis Curien](https://hal.archives-ouvertes.fr/hal-00003868/)
|
||||
- [*"Radical anti-realism and substructural logics"* -- Jacques Dubucs & Mathieu Marion](https://halshs.archives-ouvertes.fr/halshs-00000055/)
|
||||
- [*"Which Logic for the Radical Anti-Realist?"* -- Denis Bonnay & Mikael Cozic](https://halshs.archives-ouvertes.fr/halshs-00775655)
|
||||
- [*"Rule-Following and the Limits of Formalization: Wittgenstein's Considerations Through the Lens of Logic" -- Paolo Pistone*](https://hal.archives-ouvertes.fr/hal-01309218)
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Theme controller logic for DaisyUI theme switching (TypeScript version).
|
||||
* Syncs all .theme-controller checkboxes and persists theme selection in localStorage.
|
||||
*
|
||||
* This file is intended to be imported by Astro components. The function
|
||||
* auto‑runs when loaded so you only need:
|
||||
*
|
||||
* <script>
|
||||
* import "../scripts/themeController.ts";
|
||||
* </script>
|
||||
*/
|
||||
|
||||
export function setupThemeController(): void {
|
||||
// Collect every checkbox that controls the theme.
|
||||
const controllers = document.querySelectorAll<HTMLInputElement>(".theme-controller");
|
||||
|
||||
// Helper to apply a theme and keep all checkboxes in sync.
|
||||
const applyTheme = (theme: string): void => {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
controllers.forEach(cb => {
|
||||
cb.checked = cb.value === theme;
|
||||
});
|
||||
};
|
||||
|
||||
// Initialise from localStorage (or fall back to "corporate").
|
||||
const savedTheme = localStorage.getItem("theme") ?? "corporate";
|
||||
applyTheme(savedTheme);
|
||||
|
||||
// Listen for user changes.
|
||||
controllers.forEach(cb => {
|
||||
cb.addEventListener("change", () => {
|
||||
const newTheme = cb.checked ? cb.value : "corporate";
|
||||
localStorage.setItem("theme", newTheme);
|
||||
applyTheme(newTheme);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Auto‑run when this module is executed in the browser environment. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
if (typeof window !== "undefined") {
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", setupThemeController);
|
||||
} else {
|
||||
setupThemeController();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
@import "tailwindcss";
|
||||
@plugin '@tailwindcss/typography';
|
||||
@plugin "daisyui" {
|
||||
themes: corporate --default, business --prefersdark;
|
||||
}
|
||||
|
||||
/* Custom primary color */
|
||||
:root, [data-theme="corporate"] {
|
||||
--color-primary: rgb(40, 173, 145);
|
||||
--color-primary-content: #ffffff;
|
||||
}
|
||||
|
||||
[data-theme="business"] {
|
||||
--color-primary: rgb(40, 173, 145);
|
||||
--color-primary-content: #ffffff;
|
||||
}
|
||||
|
||||
/* Inter font */
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* Pagefind UI Overrides */
|
||||
.pagefind-ui {
|
||||
--pagefind-ui-scale: 0.75;
|
||||
--pagefind-ui-background: var(--color-base-100);
|
||||
--pagefind-ui-primary: var(--color-primary);
|
||||
--pagefind-ui-text: var(--color-base-content);
|
||||
--pagefind-ui-border: var(--color-primary-content);
|
||||
--pagefind-ui-border-width: var(--border);
|
||||
--pagefind-ui-border-radius: var(--radius-box);
|
||||
--pagefind-ui-font: inherit;
|
||||
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.pagefind-ui.yellow {
|
||||
--pagefind-ui-background: var(--color-warning);
|
||||
}
|
||||
|
||||
.pagefind-ui.red {
|
||||
--pagefind-ui-background: var(--color-error);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagefind-ui .pagefind-ui__drawer:not(.pagefind-ui__hidden) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-top: 0.5rem; /* leave a small gap so the input's bottom border remains visible */
|
||||
z-index: 9999;
|
||||
padding: 0 2em 1em;
|
||||
overflow-y: auto;
|
||||
box-shadow:
|
||||
0 10px 10px -5px rgba(0, 0, 0, 0.2),
|
||||
0 2px 2px 0 rgba(0, 0, 0, 0.1);
|
||||
border-bottom-right-radius: var(--pagefind-ui-border-radius);
|
||||
border-bottom-left-radius: var(--pagefind-ui-border-radius);
|
||||
background-color: var(--pagefind-ui-background);
|
||||
}
|
||||
|
||||
.pagefind-ui .pagefind-ui__result-link {
|
||||
color: var(--pagefind-ui-primary);
|
||||
}
|
||||
|
||||
.pagefind-ui .pagefind-ui__result-excerpt {
|
||||
color: var(--pagefind-ui-text);
|
||||
}
|
||||
|
||||
/* Match Pagefind search box with current DaisyUI input style (input-bordered removed since v5) */
|
||||
.pagefind-ui .pagefind-ui__search-input {
|
||||
@apply input w-full border-base-300;
|
||||
}
|
||||
|
||||
/* Ensure Pagefind UI takes full width when displayed inside the mobile search modal */
|
||||
.modal .pagefind-ui {
|
||||
width: 100% !important; /* Override the default 50 % */
|
||||
}
|
||||
|
||||
.modal .pagefind-ui__drawer:not(.pagefind-ui__hidden) {
|
||||
width: 100% !important; /* Search results span the modal width */
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [
|
||||
".astro/types.d.ts",
|
||||
"**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"dist"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
}
|
||||
}
|
||||