feat: Astro starter kit minimal et élégant

- Design minimal monochrome (fond blanc, typo Inter)
- Navigation avec Navbar (Home/About)
- Pages index et about
- Configuration Docker optimisée avec nginx
- SEO et performance optimisés
- Prêt pour la production
This commit is contained in:
2025-12-08 12:54:35 +00:00
parent 984ecf5d6c
commit 998bdaf1f0
19 changed files with 6691 additions and 157 deletions

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# 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/

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,10 +1,31 @@
# Multi-stage build pour Astro
FROM node:20-alpine AS builder
WORKDIR /app
# Copier les fichiers de dépendances
COPY package*.json ./
# Installer les dépendances
RUN npm ci
# Copier le code source
COPY . .
# Build du projet Astro
RUN npm run build
# Stage de production avec nginx
FROM nginx:alpine FROM nginx:alpine
# Copy static assets to nginx default html folder # Copier les fichiers statiques générés
COPY index.html /usr/share/nginx/html/index.html COPY --from=builder /app/dist /usr/share/nginx/html
# Expose port 80 # Copier la configuration nginx personnalisée
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Exposer le port 80
EXPOSE 80 EXPOSE 80
# Start nginx in foreground # Démarrer nginx
CMD ["nginx", "-g", "daemon off;"] CMD ["nginx", "-g", "daemon off;"]

115
README.md Normal file
View File

@@ -0,0 +1,115 @@
# 🚀 Astro Starter Kit
Un starter kit moderne optimisé pour la performance et le SEO, utilisant **Astro**, **React** et **Tailwind CSS**.
## ✨ Fonctionnalités
-**Ultra rapide** : Génération statique avec Astro
- ⚛️ **React** : Hydratation partielle intelligente (Islands Architecture)
- 🎨 **Tailwind CSS** : Styling moderne et responsive
- 🔍 **SEO optimisé** : Meta tags et structure HTML5
- 🐳 **Docker ready** : Build multi-stage optimisé
## 📦 Structure du projet
```
/
├── src/
│ ├── layouts/
│ │ └── BaseLayout.astro # Layout de base avec SEO
│ ├── components/
│ │ └── InteractiveCounter.jsx # Composant React démo
│ ├── pages/
│ │ └── index.astro # Page d'accueil
│ └── styles/
│ └── global.css # Styles Tailwind
├── public/
├── Dockerfile # Build multi-stage
├── docker-compose.yml
└── astro.config.mjs
```
## 🚀 Démarrage rapide
### Développement local
```bash
# Installer les dépendances
npm install
# Lancer le serveur de dev
npm run dev
```
Le site sera accessible sur `http://localhost:4321`
### Build de production
```bash
# Générer les fichiers statiques
npm run build
# Prévisualiser le build
npm run preview
```
### Docker
```bash
# Build et lancement avec Docker Compose
docker compose up -d --build
# Le site sera accessible sur http://localhost:8080
```
## 🎯 Concepts clés
### Hydratation partielle (Islands Architecture)
Astro envoie **zéro JavaScript par défaut**. Les composants React ne sont hydratés que si vous utilisez une directive `client:*` :
```astro
<!-- Rendu statique uniquement (pas de JS) -->
<InteractiveCounter />
<!-- Hydraté côté client (interactif) -->
<InteractiveCounter client:load />
```
### Directives client disponibles
- `client:load` : Hydrate immédiatement
- `client:idle` : Hydrate quand le navigateur est inactif
- `client:visible` : Hydrate quand visible dans le viewport
- `client:media` : Hydrate selon une media query
## 📝 Personnalisation
### Ajouter une nouvelle page
Créez un fichier `.astro` dans `src/pages/` :
```astro
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="Ma nouvelle page">
<h1>Contenu de ma page</h1>
</BaseLayout>
```
### Ajouter un composant React
Créez un fichier `.jsx` dans `src/components/` et utilisez-le avec une directive `client:*` pour l'interactivité.
## 🛠️ Technologies
- [Astro](https://astro.build) - Framework web moderne
- [React](https://react.dev) - Bibliothèque UI
- [Tailwind CSS](https://tailwindcss.com) - Framework CSS utility-first
- [Docker](https://www.docker.com) - Containerisation
## 📄 Licence
MIT

14
astro.config.mjs Normal file
View File

@@ -0,0 +1,14 @@
// @ts-check
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import tailwindcss from '@tailwindcss/vite';
// https://astro.build/config
export default defineConfig({
integrations: [react()],
vite: {
plugins: [tailwindcss()]
}
});

View File

@@ -1,6 +1,6 @@
services: services:
web: web:
build: . build: .
container_name: mon-site-v1 container_name: astro-starter-kit
ports: ports:
- "8080:80" - "8080:80"

View File

@@ -1,133 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bienvenue !</title>
<style>
:root {
--primary: #6366f1;
--secondary: #a855f7;
--bg: #0f172a;
--text: #f8fafc;
}
body {
margin: 0;
font-family: 'Inter', system-ui, -apple-system, sans-serif;
background-color: var(--bg);
color: var(--text);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden;
}
.container {
text-align: center;
padding: 2rem;
position: relative;
z-index: 10;
}
h1 {
font-size: 3.5rem;
font-weight: 800;
margin-bottom: 1rem;
background: linear-gradient(135deg, var(--primary), var(--secondary));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: fadeInDown 1s ease-out;
}
p {
font-size: 1.25rem;
color: #94a3b8;
margin-top: 0;
animation: fadeInUp 1s ease-out 0.3s backwards;
}
.card {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
padding: 3rem;
border-radius: 1.5rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
border-color: rgba(99, 102, 241, 0.3);
}
/* Ambient background blobs */
.blob {
position: absolute;
filter: blur(80px);
z-index: 0;
opacity: 0.6;
animation: pulse 8s infinite alternate;
}
.blob-1 {
top: -10%;
left: -10%;
width: 500px;
height: 500px;
background: var(--primary);
border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%;
}
.blob-2 {
bottom: -10%;
right: -10%;
width: 400px;
height: 400px;
background: var(--secondary);
animation-delay: -4s;
border-radius: 60% 40% 30% 70% / 50% 30% 50% 40%;
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0% { transform: scale(1); }
100% { transform: scale(1.1); }
}
</style>
</head>
<body>
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="container">
<div class="card">
<h1>Bienvenue</h1>
<p>Hello depuis ma VM Dockerisée ! 🐳</p>
</div>
</div>
</body>
</html>

16
nginx.conf Normal file
View File

@@ -0,0 +1,16 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Utiliser des redirections relatives
absolute_redirect off;
location / {
try_files $uri $uri/ $uri.html =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}

6223
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
package.json Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "test",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/react": "^4.4.2",
"@tailwindcss/vite": "^4.1.17",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"astro": "^5.16.4",
"react": "^19.2.1",
"react-dom": "^19.2.1",
"tailwindcss": "^4.1.17"
}
}

9
public/favicon.svg Normal file
View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 749 B

View File

@@ -1,19 +0,0 @@
# Mon Site Dockerisé
## Commandes
```bash
# Lancer
docker compose up -d --build
# Vérifier
docker compose ps
# Logs
docker compose logs -f web
# Arrêter
docker compose down
```
Site : http://localhost:8080

View File

@@ -0,0 +1,41 @@
---
const currentPath = Astro.url.pathname;
---
<nav class="border-b border-gray-200">
<div class="max-w-4xl mx-auto px-6 py-4">
<div class="flex items-center justify-between">
<a
href="/"
class="text-xl font-semibold tracking-tight text-gray-900 hover:text-gray-600 transition-colors"
>
Starter Kit
</a>
<div class="flex gap-8">
<a
href="/"
class:list={[
"text-sm font-medium transition-colors",
currentPath === "/"
? "text-gray-900"
: "text-gray-500 hover:text-gray-900",
]}
>
Home
</a>
<a
href="/about"
class:list={[
"text-sm font-medium transition-colors",
currentPath === "/about"
? "text-gray-900"
: "text-gray-500 hover:text-gray-900",
]}
>
About
</a>
</div>
</div>
</div>
</nav>

View File

@@ -0,0 +1,43 @@
---
import "../styles/global.css";
interface Props {
title?: string;
description?: string;
}
const {
title = "Astro Starter Kit",
description = "Un starter kit Astro minimal et élégant",
} = Astro.props;
---
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<meta name="generator" content={Astro.generator} />
<!-- SEO -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<!-- Google Fonts - Inter -->
<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"
/>
</head>
<body class="font-sans antialiased bg-white text-gray-900">
<slot />
</body>
</html>

61
src/pages/about.astro Normal file
View File

@@ -0,0 +1,61 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
import Navbar from "../components/Navbar.astro";
---
<BaseLayout
title="About - Astro Starter Kit"
description="À propos de ce starter kit Astro"
>
<Navbar />
<main class="max-w-4xl mx-auto px-6 py-16">
<div class="mb-16">
<h1 class="text-5xl font-bold tracking-tight mb-4">About</h1>
<p class="text-xl text-gray-600 leading-relaxed">
Un starter kit pensé pour la simplicité et l'élégance.
</p>
</div>
<div class="prose prose-gray max-w-none">
<h2 class="text-2xl font-semibold mb-4">Philosophie</h2>
<p class="text-gray-600 leading-relaxed mb-8">
Ce starter kit adopte une approche minimaliste : fournir une
base solide sans superflu, avec les outils essentiels pour
démarrer rapidement un projet web moderne.
</p>
<h2 class="text-2xl font-semibold mb-4">Technologies</h2>
<ul class="space-y-3 text-gray-600">
<li class="flex items-start">
<span class="font-medium text-gray-900 mr-2">Astro</span>
<span>— Framework web moderne avec génération statique</span
>
</li>
<li class="flex items-start">
<span class="font-medium text-gray-900 mr-2">React</span>
<span
>— Bibliothèque UI pour les composants interactifs</span
>
</li>
<li class="flex items-start">
<span class="font-medium text-gray-900 mr-2"
>Tailwind CSS</span
>
<span>— Framework CSS utility-first</span>
</li>
<li class="flex items-start">
<span class="font-medium text-gray-900 mr-2">Docker</span>
<span>— Containerisation pour un déploiement simplifié</span
>
</li>
</ul>
<div class="mt-12 pt-8 border-t border-gray-200">
<p class="text-sm text-gray-500">
Construit avec attention aux détails et à la performance.
</p>
</div>
</div>
</main>
</BaseLayout>

62
src/pages/index.astro Normal file
View File

@@ -0,0 +1,62 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
import Navbar from "../components/Navbar.astro";
---
<BaseLayout
title="Astro Starter Kit"
description="Un starter kit minimal et élégant avec Astro, React et Tailwind CSS"
>
<Navbar />
<main class="max-w-4xl mx-auto px-6 py-16">
<!-- Hero Section -->
<div class="mb-16">
<h1 class="text-5xl font-bold tracking-tight mb-4">
Astro Starter Kit
</h1>
<p class="text-xl text-gray-600 leading-relaxed">
Un point de départ minimal et élégant pour vos projets web
modernes.
</p>
</div>
<!-- Features -->
<div class="space-y-12">
<div>
<h2 class="text-2xl font-semibold mb-3">Performance</h2>
<p class="text-gray-600 leading-relaxed">
Génération statique ultra-rapide avec Astro. Zéro JavaScript
par défaut, hydratation partielle intelligente uniquement
quand nécessaire.
</p>
</div>
<div>
<h2 class="text-2xl font-semibold mb-3">Design System</h2>
<p class="text-gray-600 leading-relaxed">
Tailwind CSS intégré pour un développement rapide et
cohérent. Typographie soignée avec Inter, design épuré et
moderne.
</p>
</div>
<div>
<h2 class="text-2xl font-semibold mb-3">
Prêt pour la production
</h2>
<p class="text-gray-600 leading-relaxed">
Build Docker multi-stage optimisé, SEO configuré, structure
claire et extensible.
</p>
</div>
</div>
<!-- CTA -->
<div class="mt-16 pt-12 border-t border-gray-200">
<p class="text-sm text-gray-500">
Commencez à construire votre projet dès maintenant.
</p>
</div>
</main>
</BaseLayout>

7
src/styles/global.css Normal file
View File

@@ -0,0 +1,7 @@
@import "tailwindcss";
@layer base {
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
}
}

14
tsconfig.json Normal file
View File

@@ -0,0 +1,14 @@
{
"extends": "astro/tsconfigs/strict",
"include": [
".astro/types.d.ts",
"**/*"
],
"exclude": [
"dist"
],
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}