three.js project first

This commit is contained in:
2026-01-31 11:26:50 +04:00
parent 2444fc48a4
commit b0a9b749db
18 changed files with 109 additions and 774 deletions

4
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

View File

@@ -1,7 +1,7 @@
# Astro Starter Kit: Minimal
```sh
npm create astro@latest -- --template minimal
pnpm create astro@latest -- --template minimal
```
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
@@ -31,12 +31,12 @@ All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
| `pnpm install` | Installs dependencies |
| `pnpm dev` | Starts local dev server at `localhost:4321` |
| `pnpm build` | Build your production site to `./dist/` |
| `pnpm preview` | Preview your build locally, before deploying |
| `pnpm astro ...` | Run CLI commands like `astro add`, `astro check` |
| `pnpm astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?

View File

@@ -9,6 +9,7 @@
"astro": "astro"
},
"dependencies": {
"astro": "^5.17.1"
"astro": "^5.17.1",
"three": "^0.182.0"
}
}

76
pnpm-lock.yaml generated
View File

@@ -11,6 +11,9 @@ importers:
astro:
specifier: ^5.17.1
version: 5.17.1(rollup@4.57.1)(typescript@5.9.3)
three:
specifier: ^0.182.0
version: 0.182.0
packages:
@@ -517,23 +520,23 @@ packages:
cpu: [x64]
os: [win32]
'@shikijs/core@3.21.0':
resolution: {integrity: sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA==}
'@shikijs/core@3.22.0':
resolution: {integrity: sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==}
'@shikijs/engine-javascript@3.21.0':
resolution: {integrity: sha512-ATwv86xlbmfD9n9gKRiwuPpWgPENAWCLwYCGz9ugTJlsO2kOzhOkvoyV/UD+tJ0uT7YRyD530x6ugNSffmvIiQ==}
'@shikijs/engine-javascript@3.22.0':
resolution: {integrity: sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw==}
'@shikijs/engine-oniguruma@3.21.0':
resolution: {integrity: sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ==}
'@shikijs/engine-oniguruma@3.22.0':
resolution: {integrity: sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==}
'@shikijs/langs@3.21.0':
resolution: {integrity: sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA==}
'@shikijs/langs@3.22.0':
resolution: {integrity: sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==}
'@shikijs/themes@3.21.0':
resolution: {integrity: sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw==}
'@shikijs/themes@3.22.0':
resolution: {integrity: sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==}
'@shikijs/types@3.21.0':
resolution: {integrity: sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==}
'@shikijs/types@3.22.0':
resolution: {integrity: sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==}
'@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
@@ -1219,8 +1222,8 @@ packages:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
shiki@3.21.0:
resolution: {integrity: sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w==}
shiki@3.22.0:
resolution: {integrity: sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g==}
sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
@@ -1260,6 +1263,9 @@ packages:
engines: {node: '>=16'}
hasBin: true
three@0.182.0:
resolution: {integrity: sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==}
tiny-inflate@1.0.3:
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
@@ -1533,7 +1539,7 @@ snapshots:
remark-parse: 11.0.0
remark-rehype: 11.1.2
remark-smartypants: 3.0.2
shiki: 3.21.0
shiki: 3.22.0
smol-toml: 1.6.0
unified: 11.0.5
unist-util-remove-position: 5.0.0
@@ -1843,33 +1849,33 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.57.1':
optional: true
'@shikijs/core@3.21.0':
'@shikijs/core@3.22.0':
dependencies:
'@shikijs/types': 3.21.0
'@shikijs/types': 3.22.0
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
hast-util-to-html: 9.0.5
'@shikijs/engine-javascript@3.21.0':
'@shikijs/engine-javascript@3.22.0':
dependencies:
'@shikijs/types': 3.21.0
'@shikijs/types': 3.22.0
'@shikijs/vscode-textmate': 10.0.2
oniguruma-to-es: 4.3.4
'@shikijs/engine-oniguruma@3.21.0':
'@shikijs/engine-oniguruma@3.22.0':
dependencies:
'@shikijs/types': 3.21.0
'@shikijs/types': 3.22.0
'@shikijs/vscode-textmate': 10.0.2
'@shikijs/langs@3.21.0':
'@shikijs/langs@3.22.0':
dependencies:
'@shikijs/types': 3.21.0
'@shikijs/types': 3.22.0
'@shikijs/themes@3.21.0':
'@shikijs/themes@3.22.0':
dependencies:
'@shikijs/types': 3.21.0
'@shikijs/types': 3.22.0
'@shikijs/types@3.21.0':
'@shikijs/types@3.22.0':
dependencies:
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
@@ -1969,7 +1975,7 @@ snapshots:
prompts: 2.4.2
rehype: 13.0.2
semver: 7.7.3
shiki: 3.21.0
shiki: 3.22.0
smol-toml: 1.6.0
svgo: 4.0.0
tinyexec: 1.0.2
@@ -2948,14 +2954,14 @@ snapshots:
'@img/sharp-win32-x64': 0.34.5
optional: true
shiki@3.21.0:
shiki@3.22.0:
dependencies:
'@shikijs/core': 3.21.0
'@shikijs/engine-javascript': 3.21.0
'@shikijs/engine-oniguruma': 3.21.0
'@shikijs/langs': 3.21.0
'@shikijs/themes': 3.21.0
'@shikijs/types': 3.21.0
'@shikijs/core': 3.22.0
'@shikijs/engine-javascript': 3.22.0
'@shikijs/engine-oniguruma': 3.22.0
'@shikijs/langs': 3.22.0
'@shikijs/themes': 3.22.0
'@shikijs/types': 3.22.0
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
@@ -3002,6 +3008,8 @@ snapshots:
picocolors: 1.1.1
sax: 1.4.4
three@0.182.0: {}
tiny-inflate@1.0.3: {}
tinyexec@1.0.2: {}

3
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,3 @@
onlyBuiltDependencies:
- esbuild
- sharp

View File

@@ -1,36 +0,0 @@
---
const pageTitle = "À propos";
---
<html lang="fr">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{pageTitle}</title>
</head>
<body>
<h1>{pageTitle}</h1>
<a href="/">Accueil</a>
<a href="/about/">À propos</a>
<a href="/blog/">Blog</a>
<h1>À propos de moi</h1>
<h2>... et de mon nouveau site Astro !</h2>
<p>
Je suis en train de suivre le tutoriel d'introduction d'Astro. C'est
la deuxième page de mon site web, et c'est la première que j'ai
construite moi-même !
</p>
<p>
Ce site se mettra à jour au fur et à mesure que je compléterai
davantage le tutoriel, alors revenez régulièrement voir comment se
déroule mon parcours !
</p>
</body>
</html>

View File

@@ -1,30 +0,0 @@
---
const pageTitle = "Blog";
---
<html lang="fr">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{pageTitle}</title>
</head>
<body>
<h1>{pageTitle}</h1>
<a href="/">Accueil</a>
<a href="/about/">À propos</a>
<a href="/blog/">Blog</a>
<h1>Mon blog d'apprentissage d'Astro</h1>
<p>Voici où je vais publier mon parcours d'apprentissage d'Astro.</p>
<ul>
<li><a href="/posts/post-1/">Article 1</a></li>
<li><a href="/posts/post-2/">Article 2</a></li>
<li><a href="/posts/post-3/">Article 3</a></li>
<li><a href="/posts/post-4/">Article 4</a></li>
</ul>
</body>
</html>

View File

@@ -1,5 +1,5 @@
---
const pageTitle = "Accueil";
---
<html lang="fr">
@@ -9,13 +9,14 @@ const pageTitle = "Accueil";
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{pageTitle}</title>
<title>Three.js</title>
</head>
<body>
<h1>{pageTitle}</h1>
<a href="/">Accueil</a>
<a href="/about/">À propos</a>
<a href="/blog/">Blog</a>
<h1>Three.js</h1>
<canvas class="webgl"></canvas>
</body>
</html>
<script>
import "../scripts/three";
</script>

View File

@@ -1 +0,0 @@
{}

View File

@@ -1 +0,0 @@
{}

View File

@@ -1,33 +0,0 @@
{
"file-explorer": true,
"global-search": true,
"switcher": true,
"graph": true,
"backlink": true,
"canvas": true,
"outgoing-link": true,
"tag-pane": true,
"footnotes": false,
"properties": true,
"page-preview": true,
"daily-notes": true,
"templates": true,
"note-composer": true,
"command-palette": true,
"slash-command": false,
"editor-status": true,
"bookmarks": true,
"markdown-importer": false,
"zk-prefixer": false,
"random-note": false,
"outline": true,
"word-count": true,
"slides": false,
"audio-recorder": false,
"workspaces": false,
"file-recovery": true,
"publish": false,
"sync": true,
"bases": true,
"webviewer": false
}

View File

@@ -1,201 +0,0 @@
{
"main": {
"id": "6f65476818392d3e",
"type": "split",
"children": [
{
"id": "4792f37aa030a2bd",
"type": "tabs",
"children": [
{
"id": "c9a5ae1d384a28a9",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "post-4.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
"title": "post-4"
}
}
]
}
],
"direction": "vertical"
},
"left": {
"id": "47d0f9f12d87b6ec",
"type": "split",
"children": [
{
"id": "4acecf38ed8d32fd",
"type": "tabs",
"children": [
{
"id": "691b67d6a4302866",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {
"sortOrder": "alphabetical",
"autoReveal": false
},
"icon": "lucide-folder-closed",
"title": "Explorateur de fichiers"
}
},
{
"id": "cca9ff2f9d4c6ac4",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical"
},
"icon": "lucide-search",
"title": "Rechercher"
}
},
{
"id": "029454e004db258f",
"type": "leaf",
"state": {
"type": "bookmarks",
"state": {},
"icon": "lucide-bookmark",
"title": "Signets"
}
}
]
}
],
"direction": "horizontal",
"width": 300
},
"right": {
"id": "cbf28afbed520fd3",
"type": "split",
"children": [
{
"id": "98277055c25f849a",
"type": "tabs",
"children": [
{
"id": "c8e7bd349ecd562e",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"file": "post-4.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": true
},
"icon": "links-coming-in",
"title": "Rétrolien pour post-4"
}
},
{
"id": "cb74d3f9886f5556",
"type": "leaf",
"state": {
"type": "outgoing-link",
"state": {
"file": "post-4.md",
"linksCollapsed": false,
"unlinkedCollapsed": true
},
"icon": "links-going-out",
"title": "Liens sortants de post-4"
}
},
{
"id": "5465269b8a55292f",
"type": "leaf",
"state": {
"type": "tag",
"state": {
"sortOrder": "frequency",
"useHierarchy": true,
"showSearch": false,
"searchQuery": ""
},
"icon": "lucide-tags",
"title": "Mots-clés"
}
},
{
"id": "660c0945bc684661",
"type": "leaf",
"state": {
"type": "all-properties",
"state": {
"sortOrder": "frequency",
"showSearch": false,
"searchQuery": ""
},
"icon": "lucide-archive",
"title": "Toutes les propriétés"
}
},
{
"id": "135896c0667b9ff6",
"type": "leaf",
"state": {
"type": "outline",
"state": {
"file": "post-4.md",
"followCursor": false,
"showSearch": false,
"searchQuery": ""
},
"icon": "lucide-list",
"title": "Plan de post-4"
}
}
]
}
],
"direction": "horizontal",
"width": 300,
"collapsed": true
},
"left-ribbon": {
"hiddenItems": {
"switcher:Ouvrir le sélecteur rapide": false,
"graph:Ouvrir la vue graphique": false,
"canvas:Créer une nouvelle toile": false,
"daily-notes:Ouvrir la note quotidienne": false,
"templates:Insérer le modèle": false,
"command-palette:Ouvrir la palette de commandes": false,
"bases:Create new base": false
}
},
"active": "c9a5ae1d384a28a9",
"lastOpenFiles": [
"post-6.md",
"post-4.md",
"post-5.md",
"post-10.md",
"post-9.md",
"post-8.md",
"post-7.md",
"Configurer environnement de développement.md",
"post-3.md",
"post-2.md",
"post-1.md",
"log-1.md"
]
}

View File

@@ -1,27 +0,0 @@
---
title: 'Mon premier article de blog'
pubDate: 2026-01-30
description: "Compte rendu de ma première installation"
author: 'Apprenti Astro'
image:
url: 'https://docs.astro.build/assets/rose.webp'
alt: "Le logo Astro sur un fond sombre avec une lueur rose."
tags: ["astro", "blogging", "apprentissage en public"]
---
# Mon premier article de blog
Publié le : 2026-01-30
Bienvenue sur mon _nouveau blog_ dédié à l'apprentissage d'Astro ! Ici, je vais partager mon parcours d'apprentissage en créant un nouveau site web.
## Ce que j'ai accompli
1. **Installation d'Astro** : Tout d'abord, j'ai créé un nouveau projet Astro et configuré mes comptes en ligne.
2. **Création de pages** : Ensuite, j'ai appris à créer des pages en créant de nouveaux fichiers `.astro` et en les plaçant dans le dossier `src/pages/`.
3. **Création d'articles de blog** : C'est mon premier article de blog ! J'ai maintenant des pages Astro et des articles en Markdown !
## Ce qui vient ensuite
Je vais terminer le tutoriel d'Astro, puis continuer à ajouter plus d'articles. Restez à l'écoute pour en savoir plus.

View File

@@ -1,11 +0,0 @@
---
title: Mon deuxième article de blog
author: Apprenti Astro
description: "Après avoir appris Astro, je ne pouvais plus m'arrêter !"
image:
url: "https://docs.astro.build/assets/arc.webp"
alt: "Le logo Astro sur un fond sombre avec un arc de cercle dégradé violet."
pubDate: 2026-01-30
tags: ["astro", "blogging", "apprentissage en public", "réussites"]
---
Après une première semaine réussie d'apprentissage d'Astro, j'ai décidé d'en faire un peu plus. J'ai écrit et importé un petit composant de mémoire !

View File

@@ -1,11 +0,0 @@
---
title: Mon troisième article de blog
author: Apprenti Astro
description: "J'ai eu quelques défis, mais demander de l'aide à la communauté m'a vraiment aidé !"
image:
url: "https://docs.astro.build/assets/rays.webp"
alt: "Le logo Astro sur un fond sombre avec un arc de cercle dégradé violet."
pubDate: 2026-01-30
tags: ["astro", "apprentissage en public", "obstacles", "communauté"]
---
Ce n'était pas toujours tout rose, mais j'adore créer avec Astro. Et, la [communauté Discord](https://astro.build/chat) est vraiment sympathique et serviable !

View File

@@ -1,374 +0,0 @@
---
title: "Log de Bord : Construction du Jardin Numérique v1"
description: "Ce document est le journal de bord de la construction de mon site Astro. Il est basé sur le tutoriel officiel et adapté pour le projet 'HebelOS'."
pubDate: "2026-01-30"
version: "1.0.0"
author: "Latchimy Nicolas"
tags: ["astro", "log-de-bord", "tutoriel", "hebelos"]
---
# Log de Bord : Tutoriel Astro
Ce document est ma version personnalisée du tutoriel officiel d'Astro. Il sert de base à la construction de mon jardin numérique et de "Log" pour toutes les modifications à venir.
> [!NOTE] Objectif
> Utiliser ce guide comme référence principale pour chaque étape de développement, de la création des pages à l'ajout de l'interactivité.
---
## Unité 0 : Bienvenue à Bord
**Objectif :** Comprendre la structure du tutoriel et les prérequis.
### A propos des prérequis
Le tutoriel suppose une connaissance de base en HTML, CSS, JavaScript et Markdown. Pour toute question, la communauté est disponible sur le [Discord d'Astro](https://astro.build/chat) et les problèmes peuvent être signalés sur le [dépôt GitHub](https://github.com/withastro/docs/issues).
---
## Unité 1 : Créer et déployer votre premier site Astro
**Objectif :** Mettre en place un environnement de développement fonctionnel, créer un projet Astro de base et le déployer.
### 1.1 Environnement de développement
Mon environnement de travail pour ce projet :
- **Terminal :** Ubuntu 24.04
- **Éditeur de code :** Zed / VS Code
- **Node.js & Paquets :** `pnpm` (plus robuste que `npm` pour ce projet).
### 1.2 Créer le projet Astro
Pour initialiser le projet dans le répertoire courant en utilisant le modèle de blog :
```bash
# Nous utilisons pnpm pour sa robustesse
pnpm create astro@latest . --template blog
```
### 1.3 Écrire la première ligne de code
Le fichier `src/pages/index.astro` est le point d'entrée. Nous pouvons le modifier pour voir les changements en direct.
```astro
---
// Le frontmatter Astro (entre les '---') contient le JavaScript qui s'exécute sur le serveur.
---
<html lang="fr">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} >
<title>Mon Laboratoire</title>
</head>
<body>
<h1>Mon Jardin Numérique - HebelOS</h1>
</body>
</html>
```
### 1.4 Dépôt en ligne (Gitea)
- Créer un dépôt distant sur mon instance Gitea.
- Lier le dépôt local au dépôt distant pour versionner le code.
### 1.5 Déploiement du site
> [!TODO] Note personnelle
> Je dois documenter ici les étapes spécifiques de mon déploiement sur Raspberry Pi via Docker et Nginx Proxy Manager.
---
## Unité 2 : Pages, Routes et Markdown
**Objectif :** Créer de nouvelles pages, comprendre le routage basé sur les fichiers et commencer à utiliser Markdown pour le contenu.
### 2.1 Créer des pages Astro
Astro utilise le routage basé sur les fichiers. Chaque fichier dans `src/pages/` devient une page de votre site.
- `src/pages/index.astro` -> `mon-site.fr/`
- `src/pages/about.astro` -> `mon-site.fr/about`
- `src/pages/blog.astro` -> `mon-site.fr/blog`
Il faut ajouter des liens de navigation (`<a href="/about">`) entre les pages pour les relier.
### 2.2 Écrire le premier article en Markdown (.md)
Les articles de blog sont créés dans `src/pages/posts/`. Chaque fichier `.md` devient automatiquement une page de blog.
> [!TIP] Frontmatter
> Le bloc de texte au début d'un fichier Markdown, délimité par `---`, s'appelle le **frontmatter**. C'est là que l'on stocke les métadonnées d'une page (titre, date, description) sous forme de paires clé-valeur (format YAML). Astro lit ces données pour les utiliser dans les layouts et les pages d'index.
### 2.3 Utiliser des variables (Contenu dynamique)
On peut définir des variables dans le frontmatter d'un fichier `.astro` et les utiliser dans le template HTML avec la syntaxe `{maVariable}`.
```astro
---
const pageTitle = "À propos de moi";
const identity = {
firstName: "Nicolas",
country: "France",
hobbies: ["auto-hébergement", "BD", "RPG"],
};
const skills = ["HTML", "CSS", "JavaScript", "Astro", "Docker"];
---
<h1>{pageTitle}</h1>
<p>Je m'appelle {identity.firstName}.</p>
<p>Mes compétences :</p>
<ul>
{skills.map((skill) => <li>{skill}</li>)}
</ul>
```
### 2.4 Affichage conditionnel
On peut utiliser des opérateurs JavaScript comme `&&` (ET logique) ou l'opérateur ternaire `? :` pour afficher des éléments sous certaines conditions.
```astro
---
const happy = true;
const finished = true;
---
{happy && <p>Je suis heureux d'apprendre Astro !</p>}
{finished ? <p>J'ai terminé ce tutoriel !</p> : <p>Je suis encore en train de travailler.</p>}
```
### 2.5 Styles CSS
- **Styles locaux :** Une balise `<style>` dans un fichier `.astro` est automatiquement "scopée" (locale) : elle ne s'applique qu'aux éléments de ce fichier.
- **Styles globaux :** Pour des styles qui s'appliquent à tout le site, on crée un fichier CSS (ex: `src/styles/global.css`) et on l'importe dans les pages ou les layouts.
---
## Unité 3 : Composants Astro
**Objectif :** Décomposer l'interface en petits morceaux réutilisables (composants) pour garder le code propre et maintenable.
> [!NOTE] Convention de nommage
> Les fichiers de composants commencent par une majuscule (ex: `MonComposant.astro`). C'est une convention pour les distinguer des pages, qui sont en minuscules.
### 3.1 Créer des composants réutilisables
On crée des fichiers `.astro` dans `src/components/`. Ces fichiers peuvent ensuite être importés et utilisés dans n'importe quelle page.
**Exemple : `src/components/Navigation.astro`**
```astro
---
---
<div class="nav-links">
<a href="/">Accueil</a>
<a href="/about/">À propos</a>
<a href="/blog/">Blog</a>
</div>
```
### 3.2 Passer des données avec `Astro.props`
Les composants peuvent recevoir des données (appelées "props") depuis la page qui les utilise.
**Exemple : `src/components/Social.astro`**
```astro
---
// On récupère les props passées au composant
const { platform, username } = Astro.props;
---
<a href={`https://www.${platform}.com/${username}`}>{platform}</a>
```
**Utilisation dans `Footer.astro`**
```astro
---
import Social from './Social.astro';
---
<footer>
<Social platform="gitea" username="mon-pseudo" />
<Social platform="linkedin" username="mon-profil" />
</footer>
```
### 3.3 Ajouter un script côté client
> [!NOTE] Difficulté personnelle
> La création du menu hamburger interactif ("DIY") était une étape complexe. Le fait de la décomposer ici m'aide à la maîtriser.
Pour ajouter de l'interactivité, on crée un fichier JavaScript (ex: `src/scripts/menu.js`) et on l'importe dans une balise `<script>` à l'intérieur d'un composant ou d'une page.
**`src/scripts/menu.js`**
```javascript
document.querySelector('.hamburger').addEventListener('click', () => {
document.querySelector('.nav-links').classList.toggle('expanded');
});
```
**Dans `Header.astro`**
```astro
---
import Navigation from './Navigation.astro';
---
<header>
<button class="hamburger">Menu</button>
<Navigation />
</header>
<script>
import '../scripts/menu.js';
</script>
```
---
## Unité 4 : Layouts (Mises en page)
**Objectif :** Créer des modèles de page (`layouts`) pour partager une structure commune (header, footer, etc.) entre plusieurs pages.
### 4.1 Créer un layout de base
Un layout est un composant Astro spécial qui accepte du contenu via une balise `<slot />`.
**`src/layouts/BaseLayout.astro`**
```astro
---
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import '../styles/global.css';
const { pageTitle } = Astro.props;
---
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>{pageTitle}</title>
</head>
<body>
<Header />
<h1>{pageTitle}</h1>
<!-- Le contenu de la page sera injecté ici -->
<slot />
<Footer />
<script>
import "../scripts/menu.js";
</script>
</body>
</html>
```
### 4.2 Utiliser un layout dans une page
On importe le layout et on enveloppe le contenu de la page avec.
**`src/pages/index.astro`**
```astro
---
import BaseLayout from '../layouts/BaseLayout.astro';
const pageTitle = "Page d'accueil";
---
<BaseLayout pageTitle={pageTitle}>
<p>Ceci est le contenu de ma page d'accueil. Il sera placé dans le <slot />.</p>
</BaseLayout>
```
### 4.3 Combiner les layouts
On peut imbriquer les layouts. Par exemple, un `MarkdownPostLayout.astro` peut utiliser le `BaseLayout.astro` pour avoir une structure de base tout en ajoutant des éléments spécifiques aux articles de blog.
---
## Unité 5 : Collections de Contenu
**Objectif :** Utiliser l'API de contenu d'Astro pour organiser et valider les fichiers Markdown, et générer dynamiquement des pages.
### 5.1 Configurer les Collections
Dans `src/content/config.ts`, on définit un "schéma" pour chaque type de contenu. C'est un contrat qui garantit que tous vos fichiers Markdown ont les bonnes propriétés dans leur frontmatter.
```typescript
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
pubDate: z.date(),
description: z.string(),
author: z.string(),
tags: z.array(z.string()),
}),
});
export const collections = {
'blog': blogCollection,
};
```
Vos articles de blog doivent maintenant se trouver dans `src/content/blog/`.
### 5.2 Lister les articles (`Astro.glob` ou `getCollection`)
Pour récupérer tous les articles d'une collection et les afficher sur une page (ex: `blog.astro`).
```astro
---
// src/pages/blog.astro
import { getCollection } from 'astro:content';
import BaseLayout from '../layouts/BaseLayout.astro';
const allPosts = await getCollection('blog');
---
<BaseLayout pageTitle="Mon Blog">
<ul>
{allPosts.map(post => (
<li><a href={`/blog/${post.slug}/`}>{post.data.title}</a></li>
))}
</ul>
</BaseLayout>
```
### 5.3 Générer des pages dynamiquement
On peut créer des pages pour chaque article et chaque tag automatiquement.
- **Pages d'articles :** `src/pages/blog/[...slug].astro`
- **Pages de tags :** `src/pages/tags/[tag].astro`
Ces fichiers utilisent une fonction `getStaticPaths()` pour dire à Astro quelles pages construire au moment du build.
### 5.4 Ajouter un flux RSS
Astro facilite la création d'un flux RSS pour que les lecteurs puissent s'abonner à votre blog.
1. `pnpm add @astrojs/rss`
2. Créer un fichier `src/pages/rss.xml.js` pour configurer le flux.
---
## Unité 6 : Îlots d'interactivité (Astro Islands)
**Objectif :** Comprendre comment ajouter des composants interactifs (frameworks UI ou JS vanilla) à des pages autrement statiques.
### 6.1 Construire son premier îlot
1. **Ajouter une intégration :** `pnpm astro add react` (ou `preact`, `svelte`, etc.).
2. **Créer un composant de framework :** par exemple, `src/components/Counter.jsx`.
3. **L'utiliser dans Astro avec une directive `client:*` :** C'est cette directive qui transforme un composant en "îlot".
```astro
---
import Counter from '../components/Counter.jsx';
---
<BaseLayout pageTitle="Test d'îlot">
<p>Ce compteur est interactif, alors que le reste de la page est statique.</p>
<Counter client:load />
</BaseLayout>
```
- `client:load` : charge le JavaScript de l'îlot dès que la page se charge.
- `client:idle` : attend que la page soit chargée pour charger le JS.
- `client:visible` : attend que l'îlot soit visible à l'écran.
### 6.2 L'îlot en JavaScript "Vanilla" (Theme Toggle)
Un îlot n'a pas besoin d'un framework. Une simple balise `<script>` dans un fichier `.astro` est aussi un îlot. L'exemple du bouton pour changer de thème (clair/sombre) est parfait pour illustrer cela.
Félicitations, le log de bord de la V1 est complet !

32
src/scripts/three.js Normal file
View File

@@ -0,0 +1,32 @@
import * as THREE from "three";
// Canvas
const canvas = document.querySelector("canvas.webgl");
// Scene
const scene = new THREE.Scene();
// Object
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// Sizes
const sizes = {
width: 800,
height: 600,
};
// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
camera.position.z = 3;
scene.add(camera);
// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
});
renderer.setSize(sizes.width, sizes.height);
renderer.render(scene, camera);