diff --git a/README copy.md b/README copy.md deleted file mode 100644 index 480954cf..00000000 --- a/README copy.md +++ /dev/null @@ -1,709 +0,0 @@ -![Description de l'image](logo.svg) - -# Nexy - -> *Un framework Python moderne qui transforme le développement web en une expérience agréable et productive, construit sur la puissance de FastAPI.* - -## 📖 Table des Matières - -- [Introduction](#-introduction) -- [Installation](#-installation) -- [Concepts Fondamentaux](#-concepts-fondamentaux) -- [Routing](#-routing) -- [Controllers](#-controllers) -- [Vues et Templates](#-vues-et-templates) -- [Actions et Interactivité](#-actions-et-interactivité) -- [Organisation du Code](#-organisation-du-code) -- [Déploiement](#-déploiement) -- [Bonnes Pratiques](#-bonnes-pratiques) -- [FAQ](#-faq) - -## 🌟 Introduction - -### Le Contexte - -Le développement web en Python a toujours oscillé entre deux extrêmes : -- Des frameworks très complets mais complexes (comme Django) -- Des micro-frameworks flexibles mais nécessitant beaucoup de configuration (comme Flask) - -FastAPI a révolutionné l'écosystème en apportant performance et typage moderne. Cependant, les développeurs font toujours face à des défis : - -- Organisation complexe des projets grandissants -- Configuration répétitive des routes -- Manque de conventions claires -- Difficulté à gérer l'interface utilisateur - -### La Vision de Nexy - -Nexy est né d'une idée simple : **et si nous pouvions combiner la puissance de FastAPI avec une expérience développeur exceptionnelle ?** - -Nos principes : -1. **Convention over Configuration** : Les bonnes pratiques par défaut -2. **Intuitivité** : La structure doit être naturelle et évidente -3. **Productivité** : Moins de code répétitif, plus de fonctionnalités -4. **Évolutivité** : De la petite API au projet d'entreprise - -## 🚀 Installation - -### Prérequis - -- Python 3.12 ou supérieur -- pip (gestionnaire de paquets Python) - -### Installation Simple - -```bash -pip install nexy inquirerpy=="0.3.4" -``` - -### Création d'un Projet - -```bash -nexy new mon-projet -cd mon-projet -``` - -### Structure Initiale - -```plaintext -mon-projet/ - ├── app/ - │ ├── controller.py # Point d'entrée principal - │ └── view.html # Vue principale (optionnelle) - ├── public/ # Fichiers statiques - └── nexy-config.py # Configuration de l'application -``` - -## 🎯 Concepts Fondamentaux - -### Le Routing Automatique - -Nexy introduit un système de routing basé sur la structure des dossiers, inspiré des meilleures pratiques modernes. - -#### Structure = Routes - -```plaintext -app/ - ├── controller.py # Route: / - ├── users/ - │ ├── controller.py # Route: /users - │ └── [id]/ # Route dynamique - │ └── controller.py # Route: /users/{id} - └── blog/ - ├── controller.py # Route: /blog - └── posts/ - └── controller.py # Route: /blog/posts -``` - -### Les Controllers - -Les controllers sont le cœur de votre application. Ils définissent comment votre application répond aux requêtes HTTP. - -#### Controller Simple - -```python -# app/controller.py -async def GET(): - """Route principale : GET /""" - return {"message": "Bienvenue sur Nexy!"} - -async def POST(data: dict): - """Gestion des POST sur /""" - return {"received": data} -``` - -#### Controller avec Paramètres - -```python -# app/users/[id]/controller.py -async def GET(id: int): - """Récupère un utilisateur par ID""" - return {"user_id": id, "name": "Alice"} - -async def PUT(id: int, data: dict): - """Met à jour un utilisateur""" - return {"updated": id, "data": data} - -async def DELETE(id: int): - """Supprime un utilisateur""" - return {"deleted": id} -``` - -### Les Services - -Les services permettent d'isoler la logique métier des controllers. - -```python -# app/users/service.py -class UserService: - def __init__(self): - self.users = [] - - def get_all(self): - return self.users - - def add_user(self, user): - self.users.append(user) - return user - -# app/users/controller.py -from .service import UserService - -service = UserService() - -async def GET(): - return {"users": service.get_all()} - -async def POST(data: dict): - return {"created": service.add_user(data)} -``` - -### Les Vues - -Nexy inclut un système de templates puissant pour créer des interfaces utilisateur dynamiques. - -#### Vue Simple - -```html - - - - - Mon App Nexy - - -

Bienvenue sur {{title}}

- - - -``` - -#### Composants Réutilisables - -```html - -{% macro Button(text, type="button") %} - -{% endmacro %} - - -{% from "app/components/button.html" import Button %} - -
- {{ Button(text="Connexion", type="primary") }} - {{ Button(text="Annuler", type="secondary") }} -
-``` - -### Les Layouts - -Nexy supporte les layouts imbriqués pour une meilleure organisation des vues. - -```html - - - - - {% block title %}{% endblock %} - - - - -
- {{children | safe}} -
- - - - -``` - -[Suite dans la prochaine partie...] - -## 🌟 **Nexy** - -> *Un framework Python conçu pour allier simplicité, performance et plaisir du développement.* - ---- - -## **📢 Un message de l'équipe Nexy** - -⚠️ *Cette documentation est en cours de création.* -L'équipe de développement travaille activement sur un **site dédié**, pour offrir une documentation complète, claire et accessible. Notre objectif est de vous fournir une **expérience développeur exceptionnelle**, adaptée aussi bien aux débutants qu'aux experts. - ---- - -## **🐍 La philosophie Python au cœur de Nexy** - -Python est un langage qui se distingue par sa **simplicité, sa lisibilité** et sa grande efficacité. C'est cette philosophie qui a inspiré Nexy : rendre le développement **plus simple**, **plus rapide**, mais sans jamais sacrifier la performance. - -### **Un constat** - -Aujourd'hui, Python regorge de frameworks backend puissants, tels que : -- **Flask** -- **FastAPI** -- **Starlette**, etc. - -Ces outils sont indéniablement **performants et modulaires**, mais leur **documentation** peut parfois être intimidante et les **configurations** complexes. Même un framework complet comme **Django** peut parfois sembler lourd et difficile à aborder, même pour les développeurs expérimentés. - -### **Nexy : simplicité et efficacité** - -Chez Nexy, nous croyons que **simple ne signifie pas limité**. -Nous avons conçu Nexy pour que les développeurs puissent se concentrer sur l'essentiel sans avoir à se perdre dans des configurations complexes. - -**Ce que nous vous proposons :** -- **Démarrage rapide** : Pas de longue configuration. Vous êtes opérationnel en quelques lignes de code. -- **Code propre et modulaire** : Organisez vos projets de manière fluide et maintenez un code lisible, même pour des projets de grande envergure. -- **Performance optimale** : Profitez de la rapidité de Python tout en préservant la simplicité. - -**Le code, c'est de l'art**. Chez Nexy, chaque ligne doit être un plaisir à écrire, et votre expérience développeur compte autant que la performance du code. - ---- - -## **🎯 Nos Objectifs** - -1. **Expérience développeur** : Rendre chaque étape du projet, du démarrage au déploiement, intuitive et agréable. -2. **Performance** : Maximiser les performances sans sacrifier la simplicité. -3. **Simplicité évolutive** : Débutez simplement et restez productif même lorsque votre projet se complexifie. - -### **Ce qui nous différencie :** - -- **Structure modulaire** : Organisez vos projets de manière claire et évolutive. -- **Configuration automatique** : Nexy détecte automatiquement les routes et fichiers sans que vous ayez à vous en soucier. -- **Philosophie "Plug & Play"** : Avancez rapidement sans perdre de temps dans des configurations compliquées. - ---- - -## **📂 Structure de Projet** - -Voici un exemple d'organisation typique avec Nexy : - -```plaintext -nexy/ - ├── app/ - │ ├── controller.py # Contrôleur principal pour `/` - │ ├── model.py # Gestion des données pour `/` - │ ├── service.py # Logique métier pour `/` - │ ├── documents/ # Endpoint `/documents` - │ │ ├── controller.py # Contrôleur pour `/documents` - │ │ ├── model.py # Gestion des données pour `/documents` - │ │ ├── service.py # Logique métier pour `/documents` - │ │ └── [documentId]/ # Endpoint dynamique `/documents/{documentId}` - │ │ ├── controller.py - │ │ ├── model.py - │ │ └── service.py - │ └── users/ - │ ├── controller.py # Contrôleur pour `/users` - │ ├── model.py # Gestion des données pour `/users` - │ └── service.py # Logique métier pour `/users` - └── main.py # Point d'entrée de l'application -``` - -**💡 Astuce** : La structure des dossiers reflète vos routes, vous offrant ainsi une lisibilité immédiate et une organisation naturelle. - ---- - -# Pré-requis - -> Veuillez vous assurer que vous utilisez `Python >= 3.12`, car Nexy n'est **pas compatible** avec les versions `Python < 3.12`. - -## Comment vérifier votre version de Python ? -Exécutez cette commande dans votre terminal : - -```shell - python --version - -``` - - - ----- -## **🚀 Installation et Démarrage** - -### Étape 1 : Créez un répertoire pour votre projet et placez-vous dedans - - -1. Installez Nexy et ses dépendances : - ```shell - pip install nexy inquirerpy=="0.3.4" - ``` - -Votre API est maintenant accessible sur **http://127.0.0.1:8000** 🎉 - -Une fois que l'application est en cours d'exécution, tu peux accéder à la documentation Swagger en naviguant vers **http://localhost:8000/docs** dans ton navigateur. - ---- - -## **🧩 Concepts Clés avec des Exemples** - -### 1. **Contrôleur de Base** - -Chaque route est définie dans un fichier `controller.py`. Exemple : -```python -# app/controller.py -async def GET(): - return {"message": "Hello, world"} - -async def POST(data: dict): - return {"message": "Voici vos données", "data": data} -``` - -### 2. **Routes Dynamiques** - -Les routes dynamiques sont automatiquement détectées : -```plaintext -app/documents/[documentId]/controller.py -``` -```python -# app/documents/[documentId]/controller.py -async def GET(documentId: int): - return {"documentId": documentId, "message": "Document trouvé"} -``` - -### 3. **Architecture Modulaire avec `model` et `service`** - -Séparez la logique métier et la gestion des données : -```python -# app/users/controller.py -from .service import get_users, add_user - -async def GET(): - users = get_users() - return {"users": users} - -async def POST(user: dict): - return add_user(user) -``` - -```python -# app/users/service.py -from .model import User - -def get_users(): - return User.all() - -def add_user(data: dict): - user = User(**data) - user.save() - return {"message": "Utilisateur ajouté", "user": user} -``` - ---- - - - -## **📚 Pourquoi Nexy ?** - -- **Pour les débutants** : Vous trouverez une approche simple, sans surcharge de concepts, pour apprendre à coder rapidement. -- **Pour les experts** : La structure modulaire et la performance vous permettront de réaliser des projets de grande envergure tout en gardant un code propre et bien organisé. -- **Pour tous les développeurs** : Profitez de la facilité d'utilisation tout en écrivant un code performant et élégant. - -Avec Nexy, vous allez découvrir un framework **simple, puissant et agréable à utiliser**. Ce n'est pas seulement un framework : c'est un outil pour **libérer votre créativité**, **accélérer votre développement**, et surtout, **vous faire apprécier chaque ligne de code**. - ---- - - -## **📢 Contribuez à Nexy !** - -🚀 Nexy est open-source et vous attend sur [GitHub](https://github.com/NexyPy/Nexy). Partagez vos idées, améliorez le framework et faites partie de la révolution backend Python. - -**💡 Nexy : Plus qu'un framework, un outil pour vous.** ---- - - -## 🔄 Actions et Interactivité - -### Le Système d'Actions - -Nexy introduit un système d'actions puissant qui permet de créer des interfaces interactives sans écrire de JavaScript complexe. - -#### Actions Simples - -```html - - - - -
- Compteur: {{count}} -
-``` - -```python -# app/actions.py -count = 0 - -def increment(): - global count - count += 1 - return count -``` - -#### Actions avec Paramètres - -```html -
- - -
- - -``` - -### Gestion d'État - -Nexy permet de gérer l'état de votre application de manière simple et efficace. - -```python -# app/state.py -from nexy import State - -users = State([]) # État initial - -def add_user(name: str): - users.set([*users.get(), {"name": name}]) - return users.get() - -def remove_user(id: int): - users.set([u for u in users.get() if u.id != id]) - return users.get() -``` - -## 📦 Organisation du Code - -### Structure Recommandée - -```plaintext -mon-projet/ - ├── app/ - │ ├── controller.py # Contrôleur principal - │ ├── view.html # Vue principale - │ ├── actions.py # Actions globales - │ ├── components/ # Composants réutilisables - │ │ ├── Button.html - │ │ └── Card.html - │ ├── users/ # Module Users - │ │ ├── controller.py - │ │ ├── view.html - │ │ ├── actions.py - │ │ └── service.py - │ └── blog/ # Module Blog - │ ├── controller.py - │ ├── view.html - │ └── [slug]/ - │ └── controller.py - ├── public/ # Fichiers statiques - │ ├── css/ - │ ├── js/ - │ └── images/ - ├── tests/ # Tests - └── nexy-config.py # Configuration -``` - -### Bonnes Pratiques - -#### 1. Organisation Modulaire - -Regroupez les fonctionnalités liées dans des modules : - -```plaintext -app/users/ - ├── controller.py # Gestion des requêtes - ├── service.py # Logique métier - ├── view.html # Interface utilisateur - └── actions.py # Interactions utilisateur -``` - -#### 2. Séparation des Responsabilités - -```python -# app/users/controller.py -from .service import UserService - -service = UserService() - -async def GET(): - return service.get_users() - -# app/users/service.py -class UserService: - def get_users(self): - # Logique métier isolée - return [...] -``` - -## 🛠️ Outils de Développement - -### CLI Nexy - -```bash -# Création -nexy new mon-projet # Nouveau projet -nexy g co users # Nouveau controller -nexy g s users # Nouveau service - -# Développement -nexy dev # Serveur de développement -nexy build # Construction pour production -``` - -### Hot Reload - -Nexy inclut un système de rechargement automatique en développement : -- Modifications de code Python -- Changements dans les templates -- Mise à jour des fichiers statiques - -## 🚀 Déploiement - -### Construction pour Production - -```bash -nexy build -``` - -### Configuration de Production - -```python -# nexy-config.py -from nexy import Nexy - -app = Nexy( - production=True, - static_cache=True -) -``` - -### Plateformes Supportées - -- Vercel -- Heroku -- Docker -- VPS classique - -## 🎯 Exemples Complets - -### 1. Application Todo - -```python -# app/todos/controller.py -from nexy import HTMLResponse, CustomResponse - -todos = [] - -@CustomResponse(type=HTMLResponse) -async def GET(): - return {"todos": todos} - -async def POST(data: dict): - todos.append(data) - return {"status": "success"} -``` - -```html - -{% from "app/components/button.html" import Button %} - -
-
- - {{ Button(text="Ajouter") }} -
- - -
-``` - -### 2. API REST - -```python -# app/api/users/controller.py -from typing import List -from pydantic import BaseModel - -class User(BaseModel): - id: int - name: str - email: str - -users: List[User] = [] - -async def GET(): - return {"users": users} - -async def POST(user: User): - users.append(user) - return {"status": "created", "user": user} -``` - -## 🤝 Contribution - -1. Fork le projet -2. Créez votre branche (`git checkout -b feature/AmazingFeature`) -3. Committez vos changements (`git commit -m 'Add AmazingFeature'`) -4. Push vers la branche (`git push origin feature/AmazingFeature`) -5. Ouvrez une Pull Request - -## 📚 Ressources - -- [Documentation Officielle](https://docs.nexy.py) -- [Guide de Démarrage](https://docs.nexy.py/getting-started) -- [Exemples](https://github.com/nexy/examples) -- [Discord Community](https://discord.gg/nexy) - -## ❓ FAQ - -### Q: Nexy est-il prêt pour la production ? -R: Oui ! Nexy est construit sur FastAPI et suit les meilleures pratiques de développement. - -### Q: Puis-je utiliser Nexy pour des APIs uniquement ? -R: Absolument ! Bien que Nexy excelle dans les applications full-stack, il est parfait pour les APIs REST. - -### Q: Comment contribuer à Nexy ? -R: Consultez notre guide de contribution et rejoignez notre Discord ! - -## 🌟 Pour Finir - -Nexy est plus qu'un framework - c'est une nouvelle façon de penser le développement web en Python. Simple mais puissant, il vous permet de vous concentrer sur ce qui compte vraiment : créer des applications exceptionnelles. - ---- - -*Fait avec ❤️ par la communauté Python* - -![Version](https://img.shields.io/badge/version-1.0.0-%2337FCCB) - -## ✨ Features Clés -- 🚀 Routing automatique basé sur la structure de fichiers -- ⚡ Réactivité native sans JavaScript -- 🔒 Sécurité intégrée avec JWT/OAuth2 -- 📦 Architecture modulaire prête pour l'entreprise \ No newline at end of file diff --git a/README.md b/README.md index 40bc8941..552e437b 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,16 @@ # Nexy -Nexy is a modern, fast, and secure framework for building web applications with Python. It is a full-stack framework that allows you to build web applications with Python. - +Nexy is a modern, fast, and secure framework for building web applications with Python. It combines the power of Python with modern web development practices to create high-performance, scalable applications. With built-in support for async operations, type safety, and a rich ecosystem of plugins, Nexy makes it easy to build robust web applications. +## Features +- 🚀 **Fast**: Built on top of modern Python async capabilities +- 🛡️ **Secure**: Built-in security features and best practices +- 🔧 **Extensible**: Rich plugin ecosystem +- 📦 **Full-stack**: Integrated frontend and backend solutions +- 🎯 **Type-safe**: First-class TypeScript-like type support +- 🔥 **Hot Reload**: Automatic reloading during development ## Getting Started -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +First, create a new Nexy project: diff --git a/bun.lockb b/bun.lockb index 3c1b39fd..deacbd68 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/nexy.vs.others.md b/nexy.vs.others.md deleted file mode 100644 index b88949e1..00000000 --- a/nexy.vs.others.md +++ /dev/null @@ -1,454 +0,0 @@ -# Nexy vs Autres Frameworks Python - -## Table des Matières - -1. [Routing & Réponses](#1-routing--réponses) -2. [Templates & Layouts](#2-templates--layouts) -3. [État & Réactivité](#3-état--réactivité) -4. [WebSockets & Temps Réel](#4-websockets--temps-réel) -5. [Formulaires & Validation](#5-formulaires--validation) -6. [Middleware & Hooks](#6-middleware--hooks) -7. [CLI & Développement](#7-cli--développement) -8. [Sécurité & Performance](#8-sécurité--performance) -9. [Déploiement & Production](#9-déploiement--production) - -## 1. Routing & Réponses - -### Django -```python -# urls.py -urlpatterns = [ - path('users/', views.user_list), - path('users//', views.user_detail), -] - -# views.py -def user_list(request): - users = User.objects.all() - return render(request, 'users/list.html', {'users': users}) -``` -➡️ **Limitations**: -- Configuration manuelle des URLs -- Séparation URLs/Vues -- Pas de layouts imbriqués natifs - - - - - -### FastAPI -```python -@app.get("/users", response_class=HTMLResponse) -async def get_users(): - return """...""" - -@app.get("/users/{id}") -async def get_user(id: int): - return {"user": get_user(id)} -``` -➡️ **Limitations**: -- Pas de système de templates intégré -- Gestion manuelle du type de réponse - -### Nexy -```python -# app/users/controller.py -from nexy import CustomResponse, HTMLResponse, JSONResponse - -@CustomResponse(type=HTMLResponse) # Cherche view.html automatiquement -async def GET(): - """Route: /users""" - return {"users": get_users()} - -@CustomResponse(type=JSONResponse) -async def API(): - """Route: /users/api""" - return {"users": get_users()} - -# app/users/[id]/controller.py -from fastapi import Depends -from .dependencies import get_user_or_404 - -async def GET( - id: int, - user = Depends(get_user_or_404) # Fonctionnalités FastAPI -): - return {"user": user} -``` - -### Layouts Imbriqués Nexy -```html - - - - - {% block title %}{% endblock %} - - - -
{{ children | safe }}
- - - - -{% extends "app/layout.html" %} -
- -
{{ children | safe }}
-
- - -{% extends "app/users/layout.html" %} -
-
{% include "components/user-header.html" %}
- {{ children | safe }} -
-``` - -### Structure des Fichiers Nexy -```plaintext -app/ - ├── layout.html # Layout principal - ├── controller.py # GET / - ├── view.html # Vue principale - ├── users/ - │ ├── layout.html # Layout users - │ ├── controller.py # GET /users - │ ├── view.html # Vue liste users - │ └── [id]/ - │ ├── layout.html # Layout détail user - │ ├── controller.py # GET /users/{id} - │ └── view.html # Vue détail user -``` - -### Avantages Nexy -1. **Convention Over Configuration** - - Routes basées sur les dossiers - - Détection automatique des templates - - Types de réponses intelligents - -2. **Héritage FastAPI** - - Dépendances - - Validation Pydantic - - OpenAPI/Swagger - -3. **Layouts Puissants** - - Imbrication illimitée - - Composants réutilisables - - Héritage flexible - -[Suite dans la prochaine partie...] - -## La Révolution Nexy - -Nexy réinvente le développement web Python en combinant : -- La **simplicité** que les développeurs méritent -- La **performance** dont les applications modernes ont besoin -- La **réactivité** que les utilisateurs attendent - -### 1. Routing Intelligent - -**Avant (Django/Flask/FastAPI)** -```python -# Django -urlpatterns = [ - path('users/', views.users), - path('users//', views.user_detail), -] - -# Flask -@app.route('/users/') -def user_detail(id): - pass - -# FastAPI -@app.get('/users/{id}') -def user_detail(id: int): - pass -``` - -**Avec Nexy** -```python -# app/users/[id]/controller.py -async def GET(id: int): - return {"user": get_user(id)} -``` - -### 2. Templates Réactifs - -**Avant** -```html - -
- {% for user in users %} -
  • {{ user.name }}
  • - {% endfor %} -
    - -``` - -**Avec Nexy** -```html - -
    - {% for user in users %} -
  • {{ user.name }}
  • - {% endfor %} -
    -``` - -### 3. Actions Serveur - -**Avant** -```javascript -// JavaScript traditionnel -async function deleteUser(id) { - await fetch(`/api/users/${id}`, { - method: 'DELETE' - }); - await updateUI(); -} -``` - -**Avec Nexy** -```html - - -``` - -### 4. Performance - -```plaintext -Benchmark: 1000 requêtes simultanées - -Framework | Temps de Réponse | Mémoire -----------|-----------------|---------- -Django | 180ms | 512MB -Flask | 120ms | 128MB -FastAPI | 45ms | 64MB -Nexy | 45ms | 64MB -``` - -## Pourquoi Nexy ? - -### Pour les Startups -- Développement rapide -- De l'idée à la production en minutes -- Scaling sans effort - -### Pour les Entreprises -- Code maintenable -- Performance optimale -- Sécurité intégrée - -### Pour les Développeurs -- DX exceptionnelle -- Moins de code -- Plus de fonctionnalités - -## L'Innovation Nexy - -1. **File-based Routing** - - Structure intuitive - - Zéro configuration - - Routes dynamiques automatiques - -2. **Réactivité Native** - - Pas de JavaScript complexe - - État synchronisé automatiquement - - Performance optimale - -3. **Actions Serveur** - - Communication client-serveur simplifiée - - Sécurité par défaut - - Réactivité instantanée - -## En Résumé - -Nexy n'est pas juste un nouveau framework - c'est une nouvelle façon de penser le développement web en Python : - -- **Plus Rapide** que Django -- **Plus Structuré** que Flask -- **Plus Complet** que FastAPI -- **Plus Moderne** que tous - -C'est le premier framework Python qui comprend vraiment les besoins des développeurs modernes. - ---- - -*"Nexy : Le framework Python qui aurait dû exister depuis le début."* - -## 2. Templates & Réactivité - -### Django -```html - -{% extends "base.html" %} -{% block content %} -
    - {% for user in users %} -
    {{ user.name }}
    - {% endfor %} -
    - - -{% endblock %} -``` - -### Flask avec HTMX -```html - -{% extends "base.html" %} -{% block content %} -
    - {% for user in users %} -
    {{ user.name }}
    - {% endfor %} -
    -{% endblock %} -``` - -### Nexy -```html - -{% from "components/user-card.html" import UserCard %} - -
    - {% for user in users %} - {{ UserCard(user=user) }} - {% endfor %} -
    - -
    - - -
    -``` - -```python -# app/users/actions.py -from nexy import State - -users = State([]) - -def add_user(name: str): - """Action appelée par le formulaire""" - current = users.get() - new_user = {"id": len(current) + 1, "name": name} - users.set([*current, new_user]) - return users.get() # Mise à jour automatique des zones 'response' - -def delete_user(id: int): - """Action appelée par les boutons de suppression""" - current = users.get() - users.set([u for u in current if u['id'] != id]) - return users.get() -``` - -### Composants Réutilisables -```html - -{% macro UserCard(user) %} -
    -

    {{ user.name }}

    -
    - - -
    -
    -{% endmacro %} - - -{% macro Modal(id) %} - -{% endmacro %} -``` - -### État Réactif -```python -# state/users.py -from nexy import State -from typing import List, Optional -from pydantic import BaseModel - -class User(BaseModel): - id: int - name: str - email: Optional[str] = None - -class UsersState: - def __init__(self): - self.users: State[List[User]] = State([]) - self.selected_user: State[Optional[User]] = State(None) - self.loading: State[bool] = State(False) - - def select_user(self, id: int): - self.loading.set(True) - user = self.users.get().find(lambda u: u.id == id) - self.selected_user.set(user) - self.loading.set(False) - return { - "user": self.selected_user.get(), - "loading": self.loading.get() - } - -users_state = UsersState() -``` - -### Avantages de la Réactivité Nexy - -1. **Réactivité Native** - - Pas de JavaScript nécessaire - - Mise à jour automatique du DOM - - État synchronisé serveur/client - -2. **Actions Serveur** - - Communication bidirectionnelle simple - - Validation côté serveur - - Retour d'erreurs intégré - -3. **Composants** - - Réutilisables - - Paramétrables - - Réactifs - -4. **État** - - Géré côté serveur - - Type-safe avec Pydantic - - Mises à jour atomiques - -[Suite dans la prochaine partie...] -Je continue avec la partie sur les WebSockets et le temps réel ? - -| Caractéristique | Nexy | FastAPI | Django | Flask | -|----------------|------|---------|--------|-------| -| **Setup Rapide** | 🚀✅ | ⚠️ | ❌ | ✅ | -| **Performance** | 🚀✅ | 🚀✅ | ⚠️ | ⚠️ | \ No newline at end of file diff --git a/package.json b/package.json index 51ddd0fd..1e886e5a 100644 --- a/package.json +++ b/package.json @@ -4,36 +4,37 @@ "private": true, "scripts": { "dev": "next dev --turbopack", - "build": "next build", + "build": "next build --turbopack", "start": "next start", "lint": "next lint" }, "dependencies": { "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", - "@next/mdx": "^15.1.6", - "@tailwindcss/postcss": "^4.0.0", - "@tailwindcss/typography": "latest", - "@types/dompurify": "^3.0.5", + "@next/mdx": "^15.3.1", + "@tailwindcss/postcss": "^4.1.4", + "@tailwindcss/typography": "^0.5.16", + "@types/dompurify": "^3.2.0", "@types/mdx": "^2.0.13", - "dompurify": "^3.2.4", + "@vercel/analytics": "^1.5.0", + "dompurify": "^3.2.5", "install": "^0.13.0", - "motion": "^12.0.11", - "next": "15.1.6", - "react": "^19.0.0", - "react-dom": "^19.0.0", + "motion": "^12.9.2", + "next": "^15.3.1", + "react": "^19.1.0", + "react-dom": "^19.1.0", "zustand": "^5.0.3" }, "devDependencies": { - "@eslint/eslintrc": "^3.2.0", - "@types/node": "^20.17.17", - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", - "eslint": "^9.19.0", + "@eslint/eslintrc": "^3.3.1", + "@types/node": "^20.17.31", + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "eslint": "^9.25.1", "eslint-config-next": "15.1.6", - "postcss": "^8.5.1", - "shiki": "^2.3.1", - "tailwindcss": "^4.0.0", - "typescript": "^5.7.3" + "postcss": "^8.5.3", + "shiki": "^2.5.0", + "tailwindcss": "^4.1.4", + "typescript": "^5.8.3" } } diff --git a/public/ai.png b/public/ai.png new file mode 100644 index 00000000..5c988be7 Binary files /dev/null and b/public/ai.png differ diff --git a/public/maskot.png b/public/maskot.png new file mode 100644 index 00000000..2a3fd2d3 Binary files /dev/null and b/public/maskot.png differ diff --git a/read.md b/read.md deleted file mode 100644 index 7585725c..00000000 --- a/read.md +++ /dev/null @@ -1,535 +0,0 @@ -# Nexy Framework - -> Un framework Python moderne qui transforme le développement web en une expérience agréable et productive, construit sur la puissance de FastAPI. - -## Table des Matières - -1. [Introduction](#introduction) -2. [Installation](#installation) -3. [Guide de Démarrage](#guide-de-démarrage) -4. [Architecture](#architecture) -5. [Fonctionnalités Principales](#fonctionnalités-principales) -6. [Fonctionnalités Avancées](#fonctionnalités-avancées) -7. [Sécurité](#sécurité) -8. [Performance](#performance) -9. [Déploiement](#déploiement) -10. [Contribution](#contribution) -11. [Ressources](#ressources) - -## Introduction - -### La Vision de Nexy - -Nexy est né d'une vision simple mais ambitieuse : créer un framework web Python qui allie la puissance de FastAPI avec une expérience développeur exceptionnelle. Notre objectif est de permettre aux développeurs de se concentrer sur la création de valeur plutôt que sur la configuration technique. - -### Pourquoi Nexy ? - -- **Simplicité d'Utilisation** : Architecture intuitive et conventions claires -- **Performance Optimale** : Basé sur FastAPI et ses fondations asynchrones -- **Productivité Maximale** : Génération automatique de code et outils CLI puissants -- **Flexibilité** : S'adapte aussi bien aux petits projets qu'aux applications d'entreprise -- **Sécurité Intégrée** : Bonnes pratiques de sécurité par défaut -- **Documentation Complète** : Guides détaillés et exemples pratiques - -### Comparaison avec d'Autres Frameworks - -| Caractéristique | Nexy | FastAPI | Django | Flask | -|----------------|------|----------|---------|-------| -| Setup Rapide | ✅ | ⚠️ | ❌ | ✅ | -| Performance | ✅ | ✅ | ⚠️ | ⚠️ | -| Batteries Included | ✅ | ❌ | ✅ | ❌ | -| Courbe d'Apprentissage | Faible | Moyenne | Élevée | Faible | - -## Installation - -### Prérequis Détaillés - -- Python 3.12 ou supérieur -- pip version 21.0 ou supérieure -- Virtualenv (recommandé) -- Git (pour le contrôle de version) - -### Installation Pas à Pas - -```bash -# 1. Créer un environnement virtuel -python -m venv venv -source venv/bin/activate # Linux/Mac -venv\Scripts\activate # Windows - -# 2. Installer Nexy et ses dépendances -pip install nexy inquirerpy=="0.3.4" - -# 3. Créer un nouveau projet -nexy new mon-projet - -# 4. Initialiser Git (optionnel mais recommandé) -cd mon-projet -git init -``` - -### Structure Initiale Détaillée - -```plaintext -mon-projet/ -├── app/ -│ ├── controller.py # Contrôleur principal -│ ├── view.html # Vue principale -│ ├── models/ # Modèles de données -│ │ └── __init__.py -│ ├── services/ # Services métier -│ │ └── __init__.py -│ └── utils/ # Utilitaires -│ └── __init__.py -├── public/ # Fichiers statiques -│ ├── css/ -│ ├── js/ -│ └── images/ -├── tests/ # Tests unitaires et d'intégration -│ └── __init__.py -├── .env # Variables d'environnement -├── .gitignore # Configuration Git -└── nexy-config.py # Configuration de l'application -``` - -## Guide de Démarrage - -### Premier Contrôleur - -```python -# app/controller.py -from typing import Dict, Optional -from pydantic import BaseModel - -class Response(BaseModel): - status: str - message: str - data: Optional[Dict] = None - -async def GET(): - """ - Point d'entrée principal - GET / - - Returns: - Response: Message de bienvenue avec statut - """ - return Response( - status="success", - message="Bienvenue sur Nexy!", - data={"version": "1.0.0"} - ) - -async def POST(data: dict): - """ - Gestion des requêtes POST sur / - - Args: - data (dict): Données reçues dans la requête - - Returns: - Response: Confirmation de réception des données - """ - return Response( - status="success", - message="Données reçues avec succès", - data=data - ) -``` - -### Première Vue - -```html - - - - - - - {{ title | default("Mon Application Nexy") }} - - - -
    - -
    - -
    -

    {{ title }}

    - -
    - {% block content %} -

    {{ message }}

    - {% endblock %} -
    -
    - -
    -

    © {{ year }} Mon Application Nexy

    -
    - - - - -``` - -## Architecture - -### Système de Routing Détaillé - -Le routing dans Nexy est basé sur la structure des dossiers, avec plusieurs options avancées : - -#### Routes Statiques - -```plaintext -app/ -├── controller.py # / -├── about/ -│ └── controller.py # /about -└── contact/ - └── controller.py # /contact -``` - -#### Routes Dynamiques - -```python -# app/users/[id]/controller.py -from typing import Union -from nexy import NotFoundError - -async def GET(id: int): - """ - Récupère un utilisateur par son ID - - Args: - id (int): ID de l'utilisateur - - Raises: - NotFoundError: Si l'utilisateur n'existe pas - - Returns: - dict: Données de l'utilisateur - """ - user = await get_user_by_id(id) - if not user: - raise NotFoundError(f"Utilisateur {id} non trouvé") - return user - -async def PUT(id: int, data: dict): - """ - Met à jour un utilisateur - - Args: - id (int): ID de l'utilisateur - data (dict): Nouvelles données - - Returns: - dict: Utilisateur mis à jour - """ - return await update_user(id, data) - -async def DELETE(id: int): - """ - Supprime un utilisateur - - Args: - id (int): ID de l'utilisateur - - Returns: - dict: Confirmation de suppression - """ - await delete_user(id) - return {"status": "success", "message": f"Utilisateur {id} supprimé"} -``` - -#### Routes avec Middleware - -```python -# app/admin/middleware.py -from nexy import Middleware -from .auth import verify_admin_token - -class AdminMiddleware(Middleware): - async def process_request(self, request): - token = request.headers.get("Authorization") - if not await verify_admin_token(token): - raise UnauthorizedError("Accès non autorisé") -``` - -### Services et Logique Métier - -```python -# app/services/user_service.py -from typing import List, Optional -from .database import Database -from ..models.user import User - -class UserService: - def __init__(self): - self.db = Database() - - async def get_all(self) -> List[User]: - """Récupère tous les utilisateurs""" - users = await self.db.query("SELECT * FROM users") - return [User(**user) for user in users] - - async def get_by_id(self, user_id: int) -> Optional[User]: - """Récupère un utilisateur par son ID""" - user = await self.db.query_one( - "SELECT * FROM users WHERE id = ?", - [user_id] - ) - return User(**user) if user else None - - async def create(self, user_data: dict) -> User: - """Crée un nouvel utilisateur""" - user_id = await self.db.insert("users", user_data) - return await self.get_by_id(user_id) - - async def update(self, user_id: int, user_data: dict) -> Optional[User]: - """Met à jour un utilisateur""" - success = await self.db.update( - "users", - user_data, - {"id": user_id} - ) - return await self.get_by_id(user_id) if success else None - - async def delete(self, user_id: int) -> bool: - """Supprime un utilisateur""" - return await self.db.delete("users", {"id": user_id}) -``` - -## Fonctionnalités Principales - -### Système de Templates Avancé - -#### Layouts - -```html - - - - - {% block title %}{% endblock %} - MonApp - {% block head %}{% endblock %} - - -
    - {% include "components/nav.html" %} -
    - -
    - {% block content %}{% endblock %} -
    - -
    - {% include "components/footer.html" %} -
    - - -``` - -#### Composants Réutilisables - -```html - -{% macro Button(text, type="button", class="", disabled=false) %} - -{% endmacro %} - - -{% from "components/button.html" import Button %} -{{ Button("Envoyer", type="submit", class="btn-primary") }} -``` - -### Gestion d'État - -```python -# app/state.py -from nexy import State, StateManager - -# État global -app_state = StateManager() - -# États spécifiques -users = State([]) -settings = State({ - "theme": "light", - "language": "fr" -}) - -# Actions -@app_state.action -def add_user(state, user): - users.set([*users.get(), user]) - return users.get() - -@app_state.action -def update_settings(state, new_settings): - settings.set({**settings.get(), **new_settings}) - return settings.get() -``` - -## Fonctionnalités Avancées - -### Validation des Données - -```python -# app/models/user.py -from pydantic import BaseModel, EmailStr, Field -from typing import Optional -from datetime import datetime - -class UserBase(BaseModel): - email: EmailStr - username: str = Field(..., min_length=3, max_length=50) - full_name: Optional[str] = None - -class UserCreate(UserBase): - password: str = Field(..., min_length=8) - -class UserUpdate(UserBase): - password: Optional[str] = Field(None, min_length=8) - -class User(UserBase): - id: int - created_at: datetime - updated_at: datetime - is_active: bool = True - - class Config: - from_attributes = True -``` - -### WebSockets - -```python -# app/websockets/chat.py -from nexy import WebSocket -from typing import List, Set -from .models import Message - -class ChatWebSocket(WebSocket): - clients: Set[WebSocket] = set() - - async def connect(self): - await self.accept() - self.clients.add(self) - await self.broadcast({"type": "join", "user": self.user.username}) - - async def disconnect(self, close_code): - self.clients.remove(self) - await self.broadcast({"type": "leave", "user": self.user.username}) - - async def receive_json(self, content): - message = Message(**content) - await self.broadcast({ - "type": "message", - "user": self.user.username, - "content": message.content - }) - - @classmethod - async def broadcast(cls, message: dict): - for client in cls.clients: - await client.send_json(message) -``` - -### Tâches en Arrière-plan - -```python -# app/tasks/scheduler.py -from nexy import Task -from datetime import timedelta - -@Task.periodic(timedelta(minutes=15)) -async def cleanup_sessions(): - """Nettoie les sessions expirées toutes les 15 minutes""" - await db.delete_expired_sessions() - -@Task.delayed -async def send_welcome_email(user_id: int): - """Envoie un email de bienvenue de façon asynchrone""" - user = await User.get(user_id) - await mailer.send( - to=user.email, - template="welcome", - context={"user": user} - ) -``` - -## Sécurité - -### Authentification - -```python -# app/auth/jwt.py -from nexy import JWT, JWTConfig -from datetime import timedelta - -jwt = JWT( - config=JWTConfig( - secret_key="votre-clé-secrète", - algorithm="HS256", - access_token_expire=timedelta(minutes=15), - refresh_token_expire=timedelta(days=7) - ) -) - -# Middleware d'authentification -from nexy import Middleware - -class AuthMiddleware(Middleware): - async def process_request(self, request): - token = request.headers.get("Authorization") - if not token: - raise UnauthorizedError() - - try: - payload = jwt.decode(token) - request.user = await User.get(payload["user_id"]) - except JWTError: - raise UnauthorizedError() -``` - -### CORS - -```python -# nexy-config.py -from nexy import Nexy, CORSConfig - -app = Nexy( - cors=CORSConfig( - allow_origins=["https://monapp.com"], - allow_methods=["GET", "POST", "PUT", "DELETE"], - allow_headers=["Authorization"], - max_age=3600 - ) -) -``` - -## Performance - -### Cache - -```python -# app/cache.py -from nexy import Cache -from datetime import timedelta - -cache = Cache() - -@cache.cached(ttl=timedelta(minutes= \ No newline at end of file diff --git a/src/app/(home)/page.tsx b/src/app/(home)/page.tsx deleted file mode 100644 index 75fbfad6..00000000 --- a/src/app/(home)/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { redirect } from "next/navigation"; - -const HomePage = () => { - const isServer = typeof window === "undefined"; - - if (isServer) { - redirect("/docs/started"); - } - return null; -}; - -export default HomePage; diff --git a/src/app/docs/(Introduction)/page.mdx b/src/app/docs/(Introduction)/page.mdx new file mode 100644 index 00000000..7d5bb022 --- /dev/null +++ b/src/app/docs/(Introduction)/page.mdx @@ -0,0 +1,55 @@ +# Introduction + +Dans l'écosystème du développement moderne, un framework efficace doit répondre à un défi majeur : +comment accélérer le développement tout en maintenant des standards de qualité élevés ? + +Nexy répond à cette problématique en combinant la puissance de FastAPI avec une approche simplifiée du développement web. Notre framework repose sur deux piliers essentiels : **des performances exceptionnelles** et **une expérience développeur optimisée**. + +___ + +## Qu'est-ce que Nexy ? + +Nexy est un framework web moderne basé sur FastAPI, conçu pour démocratiser le développement d'applications web hautes performances. + +### Pourquoi Nexy ? + + +- Rapidité de développement : Une architecture intuitive pour lancer vos projets efficacement +- Performances natives : L'excellence technique de FastAPI, enrichie d'optimisations avancées +- Simplicité d'usage : Une expérience développeur fluide et accessible +- Flexibilité : Une adaptabilité totale, du projet personnel aux architectures complexes + +Que vous construisiez une API REST, une application web complète ou un microservice, Nexy vous accompagne avec des outils conçus pour maximiser votre productivité. + +___ + +## Avant de commencer + +Pour une expérience optimale avec cette documentation, nous recommandons de maîtriser : + +- **Python** (niveau intermédiaire) - Syntaxe, programmation orientée objet +- **FastAPI** (notions de base) - Concepts des API REST et décorateurs Python + +> **Note importante :** Débutant avec FastAPI ? Notre documentation détaillée vous guidera à travers chaque concept essentiel. + +___ + +## Ce que vous allez apprendre + +Cette documentation vous permettra de : + +- Maîtriser l'installation et la configuration de Nexy rapidement +- Comprendre les principes architecturaux fondamentaux +- Développer vos premières applications avec des exemples concrets +- Adopter les meilleures pratiques de développement + + \ No newline at end of file diff --git a/src/app/docs/(Introduction)/template.tsx b/src/app/docs/(Introduction)/template.tsx new file mode 100644 index 00000000..9e97e07d --- /dev/null +++ b/src/app/docs/(Introduction)/template.tsx @@ -0,0 +1,12 @@ +import { TemplateEffect } from "@/components/(home)/docs/templateEffect"; + +type TemplateProps = { + children: React.ReactNode; +} +const Template = ({ children }: TemplateProps) => ( + + {children} + +) + +export default Template \ No newline at end of file diff --git a/src/app/docs/[...slug]/page.tsx b/src/app/docs/[...slug]/page.tsx deleted file mode 100644 index f42be41d..00000000 --- a/src/app/docs/[...slug]/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import Build from "@/components/Build"; - -export default function DocPage() { - return ( - - ) -} diff --git a/src/app/docs/authentification/[...slug]/page.mdx b/src/app/docs/authentification/[...slug]/page.mdx new file mode 100644 index 00000000..7858710d --- /dev/null +++ b/src/app/docs/authentification/[...slug]/page.mdx @@ -0,0 +1,3 @@ +authentication: + - github +--- \ No newline at end of file diff --git a/src/app/docs/authentification/page.tsx b/src/app/docs/authentification/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/basics/[...slug]/page.mdx b/src/app/docs/basics/[...slug]/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/basics/controllers/main.py b/src/app/docs/basics/controllers/main.py new file mode 100644 index 00000000..7bed3244 --- /dev/null +++ b/src/app/docs/basics/controllers/main.py @@ -0,0 +1,13 @@ +from nexy import Request, Depends +from .service import AppService + +async def POST( + userId: int, + service: Depends(AppService), + request: Request, + ) -> Dict[str, str]: + + comment_data = await request.json() + data = await service.add_comment(userId, comment_data) + + return data diff --git a/src/app/docs/basics/controllers/page.mdx b/src/app/docs/basics/controllers/page.mdx new file mode 100644 index 00000000..af4ab7fd --- /dev/null +++ b/src/app/docs/basics/controllers/page.mdx @@ -0,0 +1,297 @@ +# Contrôleurs + +Les contrôleurs sont responsables du traitement des demandes entrantes et de l'envoi des réponses au client. + +Le rôle d'un contrôleur est de gérer des requêtes spécifiques pour l'application. Le mécanisme de routage détermine quel contrôleur traitera chaque requête. + + + Dans Nexy, un contrôleur est simplement tout fichier controller.py situé dans le répertoire app ou ses sous-répertoires. + + + + + + + + + + + + + + + + +___ + +## Route + +Une route est une association entre un chemin URL et une action dans l'application. Lorsqu'un utilisateur accède à une URL spécifique, la route correspondante est identifiée et exécutée pour traiter la demande. + +Dans Nexy, une route est définie par la structure de répertoires dans le dossier app. Le répertoire app lui-même représente la route principale, et chaque sous-répertoire définit une route imbriquée. + + + + + + + + + + +### Route dynamique + +Les routes dynamiques permettent d'identifier des ressources spécifiques en utilisant des paramètres de route. Ces paramètres sont définis dans le chemin de la route et peuvent être extraits par la fonction de traitement de la route. + +Dans Nexy, une route devient dynamique lorsque le nom du répertoire ou dossier est encadré par des crochets, comme ceci : [dossier]. + + + + + + + + + + + + + + + + + Les routes dynamiques fonctionnent de la même manière pour tous les types d'endpoints. + + +___ + +## Endpoint + +Un endpoint représente un point d'interface complet exposé par l'application qui permet l'interaction avec des services, des ressources ou des fonctionnalités spécifiques. Il comprend : + +- Le chemin d'accès URL qui identifie la ressource +- Le protocole de communication (HTTP ou WebSocket) +- La fonction de traitement qui gère les requêtes entrantes + +Dans Nexy, le framework prend en charge deux types d'endpoints principaux : + +- Les endpoints HTTP +- Les endpoints WebSocket + +___ + +## Endpoints HTTP + +Les endpoints HTTP suivent le modèle requête-réponse traditionnel et sont utilisés pour effectuer des opérations CRUD (Create, Read, Update, Delete) sur des ressources. + + Pour créer un endpoint HTTP dans Nexy, il suffit de définir une fonction ( asynchrone ou pas comme dans FastAPI ) dont le nom correspond à la méthode HTTP souhaitée (GET, POST, PUT, DELETE, etc.) dans un fichier controller.py. + + +### GET + +La méthode GET est la méthode fondamentale de récupération de données. Elle permet de lire des informations sans modifier l'état du serveur, +ce qui en fait la méthode la plus sécurisée et la plus utilisée. + +Son utilisation principale concerne l'affichage des pages et la consultation des ressources comme les profils utilisateurs ou les listes de produits. + + + + Dict[str, str] : + return {"message":"Salut Espoir Loém"} +` +} +/> + + + +Dans une route dynamique, il est possible d'extraire les paramètres de la route en utilisant le nom de la route dynamique comme paramètre de la fonction . + + + + + + + + + + + + Dict[str, str] : + users = ["Espoir Loém", "Force Espoir","LOEMBA PACKA"] + return {"user": users[userId]} +` +} +/> + + +### POST + +Complémentaire à GET, la méthode POST est dédiée à la création de nouvelles ressources. Elle assure un transfert sécurisé des données vers le serveur, avec une validation systématique avant sauvegarde. + +Cette méthode est essentielle pour toutes les opérations d'ajout, que ce soit la création de comptes utilisateurs ou la publication de nouveaux contenus. + + + List[Dict[str, str]] : + userList.append({"name":"Espoir Loém", "nationality":"Congolese"}) + return userList +` +} +/> + + +Dans une route dynamique + + + + + + + + + + + + Dict[str, str]: + + comment_data = await request.json() + data = await service.add_comment(userId, comment_data) + + return data +` +} +/> + + + + + Noté que Nexy supporte les Methode HTTP suivant : + GET + POST + PUT + DELETE + OPTIONS + HEAD + PATCH + TRACE + + +Chaque endpoint HTTP est caractérisé par : +- une communication ponctuelle et sans état +- l'utilisation d'une méthode HTTP spécifique +- une structure de données d'entrée et de sortie bien définie + +___ + +## Endpoints WebSocket + +Les endpoints WebSocket établissent une connexion persistante et bidirectionnelle entre le client et le serveur, permettant des communications en temps réel. + +Ces endpoints sont particulièrement adaptés pour : +- Les applications nécessitant des mises à jour instantanées +- Les fonctionnalités de chat et de messagerie +- Les tableaux de bord en temps réel +- Les notifications push + +Un endpoint WebSocket dans Nexy maintient un état de connexion et permet l'envoi de messages dans les deux sens à tout moment, contrairement aux endpoints HTTP qui suivent un strict modèle de requête-réponse. + +### Comment créer un endpoint WebSocket ? +Tout comme pour les endpoints HTTP, il suffit de créer une fonction asynchrone nommée SOCKET dans un fichier controller.py. + + + + + + + + + + +Tout comme pour les endpoints HTTP, il est possible d'extraire les paramètres de la route en utilisant le nom de la route dynamique comme paramètre de la fonction. + + + + + + + + + + + + + + +___ + +## 👌 Bravo ! +Maintenant que vous avez appris à propos des contrôleurs et des endpoints, vous pouvez commencer à construire la structure API de votre application ! +Découvrons comment faire cela dans la section suivante. + \ No newline at end of file diff --git a/src/app/docs/basics/middleware/page.mdx b/src/app/docs/basics/middleware/page.mdx new file mode 100644 index 00000000..011ca63d --- /dev/null +++ b/src/app/docs/basics/middleware/page.mdx @@ -0,0 +1,7 @@ +# Middleware + +Middleware is a powerful feature in Nexy that allows you to intercept and modify requests before they reach your route handlers. This gives you fine-grained control over request processing and enables common functionality like authentication, logging, and request transformation. + +## Basic Usage + +To create middleware, define a function that takes a `Request` object and returns a modified request or response: diff --git a/src/app/docs/basics/page.mdx b/src/app/docs/basics/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/basics/request/page.mdx b/src/app/docs/basics/request/page.mdx new file mode 100644 index 00000000..77a8e69a --- /dev/null +++ b/src/app/docs/basics/request/page.mdx @@ -0,0 +1,604 @@ +# Request + +L'objet de la classe Request dans Nexy est votre interface principale pour accéder aux données des requêtes HTTP entrantes. Héritant directement de FastAPI, il vous offre un accès complet et simplifié aux en-têtes, paramètres, corps de requête et fichiers téléchargés. + +### Compatibilité FastAPI + +La classe Request dans Nexy hérite intégralement de FastAPI, garantissant une compatibilité totale avec l'écosystème FastAPI existant. + + + 💡 Astuce : Un objet de la classe Request est automatiquement injecté dans vos contrôleurs. Déclarez-le simplement comme paramètre typé ! + + +--- + +## Accéder à `Request` + +Pour utiliser Request , il vous suffit de l'ajouter comme paramètre dans la définition de votre fonction de contrôleur. Voici comment faire : + + + + + + + + + +___ + +## Accéder à l'URL de la Requête + +Vous pouvez obtenir l'URL complète de la requête en utilisant request.url. + + + Dict[str, str]: + return {"url_complete": str(request.url)} +` +} +/> + + +___ + +## Connaître la Méthode HTTP + +La méthode HTTP utilisée pour la requête (GET, POST, etc.) est disponible via request.method. + + + + Dict[str, str]: + return {"methode_http": request.method} +` +} +/> + + +___ + +## Obtenir l'Adresse IP du Client + +L'adresse IP du client qui a envoyé la requête est accessible via request.client.host. + + + + Dict[str, str]: + client_host = request.client.host if request.client else "Inconnu" + return {"adresse_ip_client": client_host} +` +} +/> + + + + +___ + +## Récupérer les Paramètres de Chemin + +Les paramètres de chemin sont des valeurs qui font partie de l'URL elle-même (par exemple, /utilisateurs/123123 est un paramètre). Nexy vous permet de les récupérer directement en les déclarant comme des paramètres de votre fonction de contrôleur. + + + Dict[str, str]: + # userId est automatiquement extrait de l'URL + users = { + 1: "Espoir Loém", + 2: "Force Espoir", + 3: "LOEMBA PACKA" + } + return {"user": users.get(userId, "Utilisateur non trouvé")} +` +} +/> + + +___ + +## Récupérer les Paramètres de Requête (Query Parameters) + +Les paramètres de requête sont des paires clé-valeur ajoutées à la fin de l'URL après un point d'interrogation (par exemple, /items?name=chaise&quantity=2). Vous pouvez y accéder via l'objet request.query_params. + + + Dict[str, str]: + name = request.query_params.get("name") + quantity = request.query_params.get("quantity") + return {"nom": name, "quantite": quantity} +` +} +/> + + +Il est également possible de récupérer les paramètres de requête en les déclarant directement comme paramètres dans votre fonction de contrôleur. + + + Dict[str, str]: + return {"nom": name, "quantite": quantity} +` +} +/> + + + +___ + +## Lire le Corps de la Requête (JSON) + +Pour les requêtes POST, PUT, PATCH qui envoient des données au format JSON, vous pouvez lire le corps de la requête de manière asynchrone en utilisant await request.json(). + + + + Dict[str, str]: + data = await request.json() # Lit le corps de la requête comme du JSON + return {"message": "Données JSON reçues !", "donnees": data} +`}/> + + +___ + +## Lire le Corps de la Requête (Données de Formulaire) + +Pour les requêtes qui envoient des données de formulaire (par exemple,
    application/x-www-form-urlencoded ou multipart/form-data), vous pouvez utiliser await request.form(). + + + + Dict[str, str]: + # Lit le corps de la requête comme des données de formulaire + form_data = await request.form() + username = form_data.get("username") + password = form_data.get("password") + return { + "message": "Données de formulaire reçues !", + "username": username, + "password": password + } +` +} +/> + + +___ + +## Accéder aux En-têtes de Requête + +Les en-têtes HTTP sont accessibles via request.headers. C'est un dictionnaire insensible à la casse. + + + + Dict[str, str]: + user_agent = request.headers.get("user-agent") + content_type = request.headers.get("content-type") + return {"user_agent": user_agent, "content_type": content_type} +` +} +/> + + +___ + +## Accéder aux Cookies + +Les cookies envoyés avec la requête sont accessibles via request.cookies. C'est un dictionnaire simple. + + + + Dict[str, str]: + session_id = request.cookies.get("session_id") + return {"session_id": session_id} +` +} +/> + + +___ + +## Gérer les Fichiers Téléchargés + +Pour gérer les fichiers téléchargés via un formulaire multipart/form-data, vous pouvez accéder aux fichiers via l'objet form_data retourné par await request.form(). + + Dict[str, str]: + form_data = await request.form() + upload_file = form_data.get("upload_file") + + if upload_file and upload_file.filename: + # Pour un fichier, vous pouvez lire son contenu + content = await upload_file.read() + filename = upload_file.filename + return {"nom": filename, "taille": len(content)} + return {"message": "Aucun fichier n'a été téléchargé"} +` +} +/> + + +--- + +## Accéder au Contexte de la Requête ( request.scope ) + +L'attribut request.scope est un dictionnaire qui contient le contexte de la requête ASGI (Asynchronous Server Gateway Interface). Il inclut des informations de bas niveau sur la connexion, telles que le type de protocole, l'adresse du client et du serveur, etc. + + + Dict[str, str]: + # Par exemple, vous pouvez obtenir le type de scope + scope_type = request.scope.get("type") + return {"scope_type": scope_type} +` +} +/> + + +--- + +## Accéder à l'Application ASGI ( request.app ) + +L'attribut request.app fait référence à l'application ASGI principale qui gère la requête. Dans la plupart des cas, il s'agit de votre instance d'application Nexy. + + + Dict[str, str]: + # Vous pouvez vérifier si l'objet app est présent + app_present = bool(request.app) + return {"app_instance_present": app_present} +` +} +/> + + +--- + +## Obtenir l'URL de Base ( request.base_url ) + +L'attribut request.base_url fournit l'URL de base de l'application, sans le chemin spécifique de la requête. C'est utile pour construire des URLs absolues. + + + Dict[str, str]: + base_url = str(request.base_url) + return {"base_url": base_url} +` +} +/> + + +--- + +## Accéder aux Informations du Client (`request.client`) + +L'attribut request.client est un objet Host contenant l'adresse IP et le port du client. Nous avons déjà vu request.client.host. + + + Dict[str, str]: + client_port = request.client.port if request.client else "Inconnu" + return {"client_port": client_port} +` +} +/> + + +--- + +## Gérer les Sessions ( request.session ) + +Si vous utilisez une gestion de session (par exemple, via des middlewares), l'attribut request.session vous permet d'accéder aux données de la session en cours. Notez que cela nécessite une configuration de session. + + + Dict[str, str]: + # Accéder aux données de la session + user_id = request.session.get("user_id", "Non connecté") + return {"session_user_id": user_id} +` +} +/> + + +--- + +## Informations d'Authentification (request.auth et request.user) + +Si vous utilisez un système d'authentification, request.auth et request.user contiendront les informations d'authentification et l'objet utilisateur authentifié, respectivement. Ces attributs sont généralement définis par des middlewares d'authentification. + + + Dict[str, str]: + # Vérifier si un utilisateur est authentifié + username = request.user.display_name if request.user else "Invité" + return {"current_user": username} +` +} +/> + + +--- + +## État de la Requête ( request.state ) + +L'attribut request.state est un dictionnaire que vous pouvez utiliser pour stocker des informations arbitraires liées à la requête, accessibles tout au long de son cycle de vie (par exemple, dans les middlewares ou les dépendances). + + + Dict[str, str]: + # Définir une valeur dans l'état de la requête + request.state.custom_data = "Ceci est une donnée personnalisée" + # Récupérer une valeur de l'état de la requête + data = request.state.get("custom_data") + return {"request_state_data": data} +` +} +/> + + +--- + +## Recevoir des Données Brutes ( request.receive ) + +La méthode request.receive() est une coroutine de bas niveau utilisée pour recevoir des événements ASGI. Elle est principalement utilisée en interne par Nexy / FastAPI / Starlette pour lire le corps de la requête, mais vous pouvez l'utiliser pour des cas d'utilisation avancés. + + + Dict[str, str]: + # Exemple très bas niveau de lecture du corps de la requête + # Préférer request.json() ou request.form() pour la plupart des cas + body_chunks = [] + async for chunk in request.stream(): + body_chunks.append(chunk) + raw_body = b"".join(body_chunks).decode("utf-8") + return {"raw_body_received": raw_body} +` +} +/> + + +--- + +## Générer des URLs ( request.url_for ) + +La méthode request.url_for() permet de générer des URLs pour des routes nommées. C'est très utile pour construire des liens dynamiques dans votre application. + + + Dict[str, str]: + # Générer une URL pour une route nommée + profile_url = request.url_for("user_profile", user_id=123) + # profile_url = "/users/123" Exemple statique pour l'illustration + return {"user_profile_url": profile_url} +` +} +/> + + +--- + +## Lire le Corps de la Requête en Streaming ( request.stream ) + +La méthode request.stream() est une coroutine asynchrone qui renvoie un itérateur asynchrone sur les morceaux (chunks) du corps de la requête. C'est utile pour gérer de très gros fichiers ou des flux de données. + + + Dict[str, str]: + total_size = 0 + async for chunk in request.stream(): + total_size += len(chunk) + return {"bytes_received_via_stream": total_size} +` +} +/> + + +--- + +## Accéder au Corps de la Requête Brute ( request.body ) + +La méthode request.body() est une coroutine qui lit l'intégralité du corps de la requête et le renvoie sous forme d'octets. +Une fois lu, le corps ne peut pas être relu par d'autres méthodes comme request.json() ou request.form(). + + + Dict[str, str]: + raw_body = await request.body() + reponse = { + "raw_body_length": len(raw_body), + "raw_body_preview": raw_body.decode("utf-8")[:50] + } + return reponse +` +} +/> + + +--- + +## Vérifier la Déconnexion du Client ( request.is_disconnected ) + +La méthode request.is_disconnected() permet de vérifier si le client s'est déconnecté pendant le traitement de la requête. C'est utile pour les opérations longues. + + + Dict[str, str]: + await asyncio.sleep(1) # Simuler un travail long + if await request.is_disconnected(): + return {"status": "Client déconnecté"} + return {"status": "Client toujours connecté"} +` +} +/> + + +--- + +## Fermer la Connexion ( request.close ) + +La méthode request.close() est une coroutine qui peut être utilisée pour signaler que la connexion doit être fermée. Elle est rarement appelée directement par l'utilisateur. + + + Dict[str, str]: + La méthode request.close(). + # Il est rare de devoir l'appeler manuellement + # dans votre code d'application. + return {"message": "La méthode close est gérée par le serveur ASGI."} +` +} +/> + + +--- + +## 👌 Bravo ! + +Vous avez maintenant une compréhension très complète de l'objet Request et de toutes ses fonctionnalités dans Nexy, grâce à son héritage de FastAPI. Vous êtes prêt à manipuler les données entrantes de vos applications de manière avancée ! + +Pour aller plus loin : Consultez la documentation FastAPI pour découvrir toutes les fonctionnalités héritées disponibles dans Nexy. + + + diff --git a/src/app/docs/basics/response/page.mdx b/src/app/docs/basics/response/page.mdx new file mode 100644 index 00000000..9356b19b --- /dev/null +++ b/src/app/docs/basics/response/page.mdx @@ -0,0 +1,489 @@ +# Response + +Dans Nexy, l'objet de la classe Response est votre outil principal pour construire et envoyer des réponses HTTP personnalisées au client. Il vous offre un contrôle total sur le contenu, les en-têtes, les cookies et le code de statut de vos réponses. + +### Compatibilité FastAPI + +Nexy utilise directement les classes de Response de FastAPI. Cela signifie que vous avez accès à toutes les classes de réponse standard comme JSONResponse , HTMLResponse , PlainTextResponse , RedirectResponse , StreamingResponse , et FileResponse. +Vous pouvez vous référer à la documentation officielle de FastAPI pour explorer toutes les possibilités. + + + Par défaut, si vous retournez un dictionnaire, une liste, ou un modèle Pydantic depuis votre fonction de contrôleur, Nexy le convertira automatiquement en une JSONResponse ! + + +--- + +## Réponse JSON Simple + +La méthode la plus courante pour retourner des données. Nexy convertit automatiquement les dictionnaires et listes en JSON. + + + + Dict[str, str]: + return {"message": "Bonjour le monde!", "status": "succès"} +` +} +/> + JSONResponse: + content = {"message": "Données créées", "id": 123} + return JSONResponse(content=content, status_code=201) +` +} +/> + + +--- + +## Réponse HTML + +Pour servir du contenu HTML directement depuis vos contrôleurs. + + + HTMLResponse: + html_content = """ + + + Page Nexy + + +

    Bienvenue sur Nexy!

    +

    Votre application fonctionne parfaitement.

    + + + """ + return HTMLResponse(content=html_content) +` +} +/> +
    + +--- + +## Réponse Texte Brut + +Pour retourner du texte simple sans formatage HTML. + + + PlainTextResponse: + return PlainTextResponse("Ceci est un message en texte brut.") + +def POST() -> PlainTextResponse: + return PlainTextResponse( + "Données reçues et traitées avec succès", + status_code=201 + ) +` +} +/> + + +--- + +## Redirection + +Pour rediriger les utilisateurs vers une autre URL. + + + RedirectResponse: + # Redirection temporaire (302) + return RedirectResponse(url="/dashboard", status_code=302) + +def POST() -> RedirectResponse: + # Redirection permanente (301) + return RedirectResponse(url="https://www.nexy.io", status_code=301) +` +} +/> + + +--- + +## Téléchargement de Fichiers + +Pour permettre aux utilisateurs de télécharger des fichiers. + + + FileResponse: + # Assurez-vous que le fichier existe + file_path = "static/documents/rapport.pdf" + return FileResponse( + file_path, + media_type='application/pdf', + filename="rapport_mensuel.pdf" + ) +`}/> + FileResponse: + return FileResponse( + "static/images/logo.png", + media_type='image/png' + ) +` +} +/> + + +--- + +## Réponse en Streaming + +Pour envoyer de gros volumes de données ou des flux en temps réel. + + + StreamingResponse: + return StreamingResponse(generate_data(), media_type="text/plain") +`}/> + + + +--- + +## Personnaliser les Codes de Statut + +Définir des codes de statut HTTP appropriés pour vos réponses. + + + JSONResponse: + # Création réussie - 201 Created + return JSONResponse( + content={"message": "Ressource créée", "id": 123}, + status_code=201 + ) + +def PUT() -> JSONResponse: + # Pas de contenu - 204 No Content + return JSONResponse(content=None, status_code=204) + +def GET() -> JSONResponse: + # Erreur client - 400 Bad Request + return JSONResponse( + content={"error": "Paramètres manquants"}, + status_code=400 + ) +` +} +/> + + +--- + +## Ajouter des En-têtes + +Personnaliser les en-têtes HTTP de vos réponses. + + + JSONResponse: + content = {"data": "informations sensibles"} + headers = { + "X-Custom-Header": "MaValeurPersonnalisée", + "Cache-Control": "no-cache, no-store, must-revalidate", + "X-Rate-Limit": "100", + "X-API-Version": "v1.2.0" + } + return JSONResponse(content=content, headers=headers) +`}/> + + + +--- + +## Gérer les Cookies + +Définir et supprimer des cookies dans vos réponses. + + + + JSONResponse: + """Connexion utilisateur - définir un cookie de session""" + response = JSONResponse(content={"message": "Connexion réussie"}) + response.set_cookie( + key="session_id", + value="abc123xyz789", + httponly=True, # Sécurité contre XSS + max_age=3600, # 1 heure + samesite="lax", # Protection CSRF + secure=True # HTTPS uniquement + ) + return response + +def DELETE() -> JSONResponse: + """Déconnexion - supprimer le cookie de session""" + response = JSONResponse(content={"message": "Déconnexion réussie"}) + response.delete_cookie("session_id") + return response +` +} +/> + + +--- + +## Utiliser le Décorateur @HTTPResponse + +Le décorateur @HTTPResponse de Nexy simplifie la personnalisation des réponses et améliore la documentation automatique. + + + + +

    Page avec décorateur HTTPResponse

    +

    Documentation automatique générée !

    + + + """ +`}/> + +
    + +--- + +## Gérer les Erreurs avec `HTTPException` + +La manière recommandée pour signaler des erreurs dans vos contrôleurs. + + + + + +--- + +## Réponses Personnalisées Avancées + +Créer des réponses avec des comportements spécifiques. + + + + + + +--- + +## 👌 Parfait ! + +Vous maîtrisez maintenant toutes les façons de créer et personnaliser des réponses dans Nexy. De la simple réponse JSON aux flux de données complexes, vous avez tous les outils pour construire des APIs robustes et flexibles ! + + \ No newline at end of file diff --git a/src/app/docs/basics/routing/page.mdx b/src/app/docs/basics/routing/page.mdx new file mode 100644 index 00000000..f6853a47 --- /dev/null +++ b/src/app/docs/basics/routing/page.mdx @@ -0,0 +1,152 @@ +# Le Routage dans Nexy + + + Le routage est la façon dont Nexy organise les différentes pages et fonctionnalités de votre application. C'est comme créer un plan pour votre maison, où chaque pièce (route) a son propre chemin d'accès ! + + +## Comprendre le Routage + +Imaginez votre application comme une bibliothèque : +- Chaque étagère représente un dossier +- Chaque livre représente une page ou une fonctionnalité +- Le chemin pour trouver un livre est votre route + +### Comment ça marche ? + +Nexy utilise un système de routage basé sur les fichiers. C'est très simple : **la structure de vos dossiers devient automatiquement les chemins de votre application** ! + +### Structure de Base + + + + + + + + + + + + +Quand vous créez cette structure : +- `app/controller.py` devient votre page d'accueil (`/`) +- `app/produits/controller.py` devient accessible via `/produits` + +## Les Types de Routes + +### 1. Routes Simples (Statiques) + +Ce sont les routes les plus basiques. Comme une adresse fixe ! + + + + + +**Résultat** : Quand quelqu'un visite `/produits`, il verra "Voici la liste de nos produits !" + +### 2. Routes Dynamiques + +Imaginez que vous voulez une page différente pour chaque produit. Les routes dynamiques sont là pour ça ! + +#### a) Routes avec Paramètres `[param]` + + + + + + + + + + + + + + +```python +# app/produits/[id]/controller.py +from nexy import Controller + +class ProduitDetailController(Controller): + def get(self, id: int): + # id sera automatiquement extrait de l'URL ! + return {"message": f"Voici les détails du produit numéro {id}"} +``` + + +**Comment ça marche ?** +- `/produits/1` affichera les détails du produit 1 +- `/produits/2` affichera les détails du produit 2 +- Et ainsi de suite ! + +#### b) Routes Attrape-tout `![param]` + +Ces routes sont comme des filets qui attrapent tous les chemins possibles ! + + +```python +# app/blog/![slug]/controller.py +from nexy import Controller + +class BlogController(Controller): + def get(self, slug: list): + # slug contiendra tous les segments de l'URL + return {"message": f"Blog : {'/'.join(slug)}"} +``` + + +**Exemples d'URLs capturées :** +- `/blog/2023/janvier/article` +- `/blog/technologie/python` + +#### c) Routes Privées `[_param]` + +Pour les parties de votre application qui nécessitent une authentification. + + +```python +# app/admin/[_dashboard]/controller.py +from nexy import Controller + +class AdminController(Controller): + def get(self): + # Vérification de l'authentification incluse automatiquement + return {"message": "Bienvenue dans le tableau de bord admin !"} +``` + + +## Bonnes Pratiques + + +1. **Organisez Logiquement :** + - Gardez les routes liées ensemble (ex: tout ce qui concerne les produits dans `/produits`) + - Utilisez des noms clairs et descriptifs + +2. **Simplicité d'abord :** + - Commencez par des routes simples + - Ajoutez des routes dynamiques seulement quand nécessaire + +3. **Sécurité :** + - Utilisez les routes privées pour le contenu sensible + - Vérifiez toujours les permissions + +4. **Documentation :** + - Commentez vos contrôleurs + - Gardez une liste à jour de vos routes + + + \ No newline at end of file diff --git a/src/app/docs/basics/template.tsx b/src/app/docs/basics/template.tsx new file mode 100644 index 00000000..9e97e07d --- /dev/null +++ b/src/app/docs/basics/template.tsx @@ -0,0 +1,12 @@ +import { TemplateEffect } from "@/components/(home)/docs/templateEffect"; + +type TemplateProps = { + children: React.ReactNode; +} +const Template = ({ children }: TemplateProps) => ( + + {children} + +) + +export default Template \ No newline at end of file diff --git a/src/app/docs/cli/[...slug]/page.mdx b/src/app/docs/cli/[...slug]/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/cli/page.tsx b/src/app/docs/cli/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/concepts/[...slug]/page.mdx b/src/app/docs/concepts/[...slug]/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/concepts/page.tsx b/src/app/docs/concepts/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/databases/[...slug]/page.mdx b/src/app/docs/databases/[...slug]/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/databases/page.tsx b/src/app/docs/databases/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/global-error.tsx b/src/app/docs/global-error.tsx new file mode 100644 index 00000000..6b47d54c --- /dev/null +++ b/src/app/docs/global-error.tsx @@ -0,0 +1,10 @@ +"use client" +const DocsError = () => { + return ( + <> + ddjhj + + ) +} + +export default DocsError; \ No newline at end of file diff --git a/src/app/docs/layout.tsx b/src/app/docs/layout.tsx index f9cebec4..bc6a42c6 100644 --- a/src/app/docs/layout.tsx +++ b/src/app/docs/layout.tsx @@ -1,36 +1,34 @@ -import { HeaderDocs } from "@/components/Header"; -import { SideBar } from "@/components/SideBar"; -import { MenuBottomSheet } from "@/components/Modal"; +import { SideBar } from "@/components/(home)/sideBar"; +import { dm_sans } from "@/font/google"; const DocsLayout = ({ children }: { children: React.ReactNode }) => { - - return ( - <> - -
    - - -
    {children}
    -
    -
      -
    • Introduction
    • -
    • Installation
    • -
    • Configuration
    • + return ( -
    • Usage
    • -
    • API
    • -
    • Contributing
    • -
    • License
    • -
    -
    -
    - - +
    +
    + ) +} export default DocsLayout; diff --git a/src/app/docs/page.tsx b/src/app/docs/page.tsx deleted file mode 100644 index 7c57075b..00000000 --- a/src/app/docs/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { redirect } from "next/navigation"; - -export default function Redirect() { - const isServer = typeof window === "undefined"; - - if (isServer) { - redirect("/docs/started"); - } - return null; -} diff --git a/src/app/docs/security/[...slug]/page.mdx b/src/app/docs/security/[...slug]/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/security/page.tsx b/src/app/docs/security/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/started/[slug]/page.tsx b/src/app/docs/started/[slug]/page.tsx deleted file mode 100644 index f42be41d..00000000 --- a/src/app/docs/started/[slug]/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import Build from "@/components/Build"; - -export default function DocPage() { - return ( - - ) -} diff --git a/src/app/docs/started/_services/page.tsx b/src/app/docs/started/_services/page.tsx deleted file mode 100644 index 9c955d30..00000000 --- a/src/app/docs/started/_services/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function ServicesPage() { - return ( -
    -

    Services

    -
    - ) -} diff --git a/src/app/docs/started/components/page.tsx b/src/app/docs/started/components/page.tsx deleted file mode 100644 index eb7bbc15..00000000 --- a/src/app/docs/started/components/page.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { CodeBlock } from "@/components/CodeBlock"; -import Mark from "@/components/Mark"; -import Link from "next/link"; - -export default function ComponentsPage() { - return ( -
    -

    Votre premier composant

    - - - Les composants sont essentiels dans Nexy. Ils constituent la base de vos interfaces utilisateurs (UI), ce qui en fait un excellent point de départ pour apprendre Nexy ! - - -

    Les composants : les blocs de construction de l'UI

    -

    - Sur le Web, HTML permet de créer des documents riches et structurés grâce à ses nombreuses balises comme <h1> et <li>. Nexy vous permet de combiner votre balisage avec CSS et JavaScript pour créer des composants personnalisés, réutilisables dans votre application. -

    - -

    Définir un composant

    -

    - Traditionnellement, les développeurs web écrivent le balisage de leur contenu puis ajoutent de l'interactivité avec JavaScript. Aujourd'hui, c'est une exigence de base pour de nombreux sites et applications. Nexy met l'interactivité au premier plan tout en utilisant les mêmes technologies de base : un composant Nexy est une fonction Python que vous pouvez enrichir avec du balisage. -

    - - - -

    Structure du fichier HTML pour Button

    - {{label}}\n`} - /> - -

    Utiliser un composant

    -

    - Maintenant que vous avez défini votre composant Button, vous pouvez l'imbriquer dans d'autres composants. Par exemple, vous pouvez utiliser le composant Button dans une vue : -

    - `} - /> - -

    Composants avec contenu enfant

    -

    - Le paramètre caller permet à un composant de recevoir et d'afficher du contenu enfant, transformant le composant en une balise de type bloc. -

    - - - -

    Structure du fichier HTML pour Card

    -

    - Le fichier HTML associé au composant Card utilise la variable children pour afficher le contenu capturé. -

    - {{children}}\n`} - /> - -

    Utiliser un composant avec contenu enfant

    - \n\t

    Titre de la carte

    \n\t

    Contenu de la carte

    \n`} - /> - -

    Composition de composants

    -

    - Les composants peuvent être composés pour créer des interfaces complexes. L'attribut imports permet d'utiliser d'autres composants à l'intérieur d'un composant. -

    - - - -

    Structure du fichier HTML pour Dashboard

    - \n\t

    Bienvenue, {{user.name}}

    \n\t{% for card_data in cards %}\n\t\t\n\t\t\t

    {{card_data.title}}

    \n\t\t\t

    {{card_data.content}}

    \n\t\t\t
    `} - /> - -

    Avantages du système de composants

    -

    - Utiliser le système de composants de Nexy présente plusieurs avantages : -

    -
      -
    • Réutilisation du code à travers différentes parties de l'application
    • -
    • Séparation claire entre la logique et la présentation
    • -
    • Facilité de maintenance grâce à la modularité
    • -
    • Possibilité de créer des bibliothèques de composants pour une utilisation dans plusieurs projets
    • -
    • Syntaxe intuitive similaire aux frameworks frontend modernes
    • -
    - -
    - - ← Réponses - - - Views → - -
    - - ); -} \ No newline at end of file diff --git a/src/app/docs/started/controllers/page.tsx b/src/app/docs/started/controllers/page.tsx deleted file mode 100644 index 13a8bf47..00000000 --- a/src/app/docs/started/controllers/page.tsx +++ /dev/null @@ -1,395 +0,0 @@ -import { CodeBlock } from "@/components/CodeBlock"; -import Mark from "@/components/Mark"; -import Link from "next/link"; -const HTTP_CONTROLLER = [ - { - method: "GET", - description: "La méthode GET est la méthode fondamentale de récupération de données. Elle permet de lire des informations sans modifier l'état du serveur, ce qui en fait la méthode la plus sécurisée et la plus utilisée. Son utilisation principale concerne l'affichage des pages et la consultation des ressources comme les profils utilisateurs ou les listes de produits.", - code: `# Exemple simple de GET pour récupérer un utilisateur -from nexy import Request, Depends -from .service import AppService - -async def GET( - request: Request, - service: Depends(AppService) -): - return await service.get_user()` - }, - { - method: "POST", - description: "Complémentaire à GET, la méthode POST est dédiée à la création de nouvelles ressources. Elle assure un transfert sécurisé des données vers le serveur, avec une validation systématique avant sauvegarde. Cette méthode est essentielle pour toutes les opérations d'ajout, que ce soit la création de comptes utilisateurs ou la publication de nouveaux contenus.", - code: `# Exemple de POST pour créer un nouvel utilisateur -from nexy import Request, Depends -from .service import AppService - -async def POST( - request: Request, - service: Depends(AppService) -): - new_user = await request.json() - return await service.create_user(new_user)` - }, - { - method: "PUT", - description: "La méthode PUT s'inscrit dans la logique de modification en permettant le remplacement complet d'une ressource existante. Contrairement à POST, elle nécessite l'envoi de l'intégralité des données, même celles qui ne changent pas. Cette approche garantit la cohérence des données en évitant les mises à jour partielles.", - code: `# Exemple de PUT pour mettre à jour un profil complet -from nexy import Request, Depends -from .service import AppService - -async def PUT( - request: Request, - service: Depends(AppService) -): - updated_profile = await request.json() - return await service.update_profile(updated_profile)` - }, - { - method: "DELETE", - description: "Dans la continuité des opérations de modification, la méthode DELETE assure la suppression définitive des ressources. Elle complète le cycle de vie des données en permettant leur retrait du système. Cette méthode requiert une attention particulière et souvent une confirmation de l'utilisateur pour prévenir les suppressions accidentelles.", - code: `# Exemple de DELETE pour supprimer un compte -from nexy import Request, Depends -from .service import AppService - -async def DELETE( - request: Request, - service: Depends(AppService) -): - return await service.delete_account()` - }, - { - method: "OPTIONS", - description: "La méthode OPTIONS joue un rôle crucial dans l'architecture des API en fournissant des métadonnées sur les opérations disponibles. Elle est particulièrement importante pour la sécurité CORS et permet aux clients de découvrir les capacités d'un endpoint. Les navigateurs l'utilisent automatiquement pour vérifier les autorisations avant d'effectuer certaines requêtes.", - code: `# Exemple d'OPTIONS avec configuration CORS -from nexy import Request, Depends -from .service import AppService - -async def OPTIONS( - request: Request, - service: Depends(AppService) -): - return await service.get_cors_config()` - }, - { - method: "HEAD", - description: "La méthode HEAD est une variante optimisée de GET qui ne retourne que les en-têtes HTTP. Cette approche permet de vérifier l'existence ou les métadonnées d'une ressource sans transférer son contenu, optimisant ainsi la consommation de bande passante et les performances du système.", - code: `# Exemple de HEAD pour vérifier une ressource -from nexy import Request, Depends -from .service import AppService - -async def HEAD( - request: Request, - service: Depends(AppService) -): - return await service.get_resource_headers()` - }, - { - method: "PATCH", - description: "Complétant les capacités de PUT, la méthode PATCH permet des modifications partielles et ciblées des ressources. Cette approche plus flexible optimise les performances en ne transmettant que les données nécessaires. Elle est particulièrement adaptée pour les mises à jour fréquentes de champs spécifiques.", - code: `# Exemple de PATCH pour modifier partiellement -from nexy import Request, Depends -from .service import AppService - -async def PATCH( - request: Request, - service: Depends(AppService) -): - changes = await request.json() - return await service.update_partial(changes)` - }, - { - method: "TRACE", - description: "La méthode TRACE complète la suite des outils de diagnostic en permettant de suivre le parcours exact d'une requête à travers le réseau. Cette fonctionnalité est essentielle pour le débogage des problèmes de routage et la compréhension des transformations appliquées aux requêtes.", - code: `# Exemple de TRACE pour suivre une requête -from nexy import Request, Depends -from .service import AppService - -async def TRACE( - request: Request, - service: Depends(AppService) -): - return await service.trace_request(request)` - } -]; - -const DYNAMIC_CONTROLLER = [ - { - method: "GET", - description: "Dans une route dynamique, la méthode GET acquiert une dimension supplémentaire grâce au paramètre 'slug'. Cette approche permet une identification précise des ressources, essentielle pour la récupération de contenus spécifiques comme des articles de blog ou des profils utilisateurs individuels.", - code: `# Exemple de GET dynamique pour un article de blog -from nexy import Request, Depends -from .service import AppService - -async def GET( - slug: str, - request: Request, - service: Depends(AppService) -): - return await service.get_article(slug)` - }, - { - method: "POST", - description: "La méthode POST en contexte dynamique permet la création de ressources dans des contextes spécifiques. Cette fonctionnalité est particulièrement utile pour l'ajout d'éléments liés à une ressource existante, comme des commentaires sur un article ou des sous-éléments dans une collection.", - code: `# Exemple de POST pour ajouter un commentaire -from nexy import Request, Depends -from .service import AppService - -async def POST( - slug: str, - request: Request, - service: Depends(AppService) -): - comment_data = await request.json() - return await service.add_comment(slug, comment_data)` - } -]; - -const WEBSOCKET_CONTROLLER = [ - { - method: "SOCKET", - description: "Le contrôleur WebSocket établit une communication bidirectionnelle persistante entre le client et le serveur. Cette technologie est fondamentale pour les applications nécessitant des mises à jour en temps réel, comme les systèmes de messagerie instantanée ou les tableaux de bord dynamiques.", - code: `# Exemple de WebSocket pour un chat en direct -from nexy import WebSocket, Depends -from .service import AppService - -async def SOCKET( - ws: WebSocket, - service: Depends(AppService) -): - await service.handle_websocket(ws)` - } -]; - -const WEBSOCKET_CONTROLLER_DYNAMIC = [ - { - method: "SOCKET", - description: "Les WebSockets dynamiques étendent les capacités des WebSockets standards en permettant des connexions contextuelles via le paramètre slug. Cette approche permet la création de canaux de communication dédiés, particulièrement adaptés pour les salles de discussion privées ou les flux de données personnalisés.", - code: `# Exemple de WebSocket pour une salle de chat privée -from nexy import WebSocket, Depends -from .service import AppService - -async def SOCKET( - slug: str, - ws: WebSocket, - service: Depends(AppService) -): - await service.handle_dynamic_websocket(slug, ws)` - } -]; - -const TEMPLATE_CONTROLLER = [ - { - method: "VIEW", - description: "La méthode VIEW transforme les données en interfaces utilisateur structurées. Cette méthode, enrichie par le décorateur @component, permet la création de pages web dynamiques en combinant logique métier et présentation. Elle représente une évolution naturelle de la méthode GET en retournant du contenu HTML formaté.", - code: `# Exemple de VIEW pour une page de profil -from nexy import component, Depends -from .service import AppService -from components import Profile, UserStats - -@component( - import = [Profile, UserStats] -) -def VIEW( - service: Depends(AppService) -): - return service.get_profile_data()` - }, - { - method: "LAYOUT", - description: "La méthode LAYOUT définit la structure globale de l'application. Elle gère les éléments communs comme l'en-tête, le pied de page et la navigation. Cette méthode, utilisée conjointement avec le décorateur @component, assure une cohérence visuelle à travers l'application.", - code: `# Exemple de LAYOUT avec navigation et footer -from nexy import component, Depends -from .service import AppService -from components import Navbar, Footer, Sidebar - -@component( - import = [Navbar, Footer, Sidebar] -) -def LAYOUT( - service: Depends(AppService) -): - return service.get_layout_data()` - } -]; - -const TEMPLATE_CONTROLLER_DYNAMIC = [ - { - method: "VIEW", - description: "La méthode VIEW en contexte dynamique permet la création de pages personnalisées basées sur le paramètre slug. Cette approche permet d'adapter la présentation en fonction du contexte, idéale pour les profils utilisateurs ou les articles de contenu spécifiques.", - code: `# Exemple de VIEW pour un profil utilisateur spécifique -from nexy import component, Depends -from .service import AppService -from components import UserProfile, ActivityFeed - -@component( - import = [UserProfile, ActivityFeed] -) -def VIEW( - slug: str, - service: Depends(AppService) -): - return service.get_dynamic_profile_data(slug)` - }, - { - method: "LAYOUT", - description: "Le LAYOUT dynamique étend les capacités de mise en page en fonction du contexte fourni par le slug. Cette flexibilité permet d'adapter la structure globale selon les besoins spécifiques, comme des thèmes personnalisés ou des dispositions sectorielles.", - code: `# Exemple de LAYOUT dynamique pour différentes sections -from nexy import component, Depends -from .service import AppService -from components import DynamicNav, Footer - -@component( - import = [DynamicNav, Footer] -) -def LAYOUT( - slug: str, - service: Depends(AppService) -): - return service.get_dynamic_layout_data(slug)` - } -]; - -export default function ControllersPage() { - return ( -
    -

    Les Contrôleurs

    - - - Un contrôleur est simplement un fichier controller.py qui gère les requêtes de votre application. Il en existe trois types : HTTP pour les requêtes web classiques, WEBSOCKET pour le temps réel, et TEMPLATE pour vos vues. Petit conseil important : écrivez toujours vos fonctions de contrôleur en MAJUSCULES ! - - -

    Routes Statiques : Les Bases

    - -

    - Une route statique, c'est comme une adresse fixe - par exemple / ou /contact. Son contrôleur vit dans un fichier controller.py bien rangé dans son dossier. -

    - - - -

    Le Contrôleur HTTP : Votre Boîte à Outils Web

    - - - Le contrôleur HTTP est comme un chef d'orchestre qui dirige le trafic web avec ses méthodes : - GET (lecture), - POST (création), - PUT (mise à jour complète), - DELETE (suppression), - PATCH (mise à jour partielle), - HEAD (vérification), - OPTIONS (informations), - TRACE (débogage). - - - {HTTP_CONTROLLER.map(({ method, description, code }) => ( -
    -

    {method}

    -

    {description}

    - -
    - ))} - -

    Le Contrôleur WebSocket : Communication en Temps Réel

    - - - Les WebSockets, c'est la magie du temps réel ! Avec la méthode SOCKET, créez des applications interactives qui réagissent instantanément. - - - {WEBSOCKET_CONTROLLER.map(({ method, description, code }) => ( -
    -

    {method}

    -

    {description}

    - -
    - ))} - -

    Le Contrôleur Template : L'Art de la Présentation

    - - - Les templates donnent vie à votre interface avec deux méthodes magiques : VIEW pour vos pages et LAYOUT pour la structure globale. - - - {TEMPLATE_CONTROLLER.map(({ method, description, code }) => ( -
    -

    {method}

    -

    {description}

    - -
    - ))} - -

    Routes Dynamiques : La Flexibilité en Action

    - -

    - Les routes dynamiques sont comme des variables dans votre URL ! Par exemple : /utilisateurs/alice ou /produits/42. Elles s'adaptent à vos besoins ! -

    - - - - {DYNAMIC_CONTROLLER.map(({ method, description, code }) => ( -
    -

    {method}

    -

    {description}

    - -
    - ))} - -

    WebSockets Dynamiques : Communication Personnalisée

    - - {WEBSOCKET_CONTROLLER_DYNAMIC.map(({ method, description, code }) => ( -
    -

    {method}

    -

    {description}

    - -
    - ))} - -

    Templates Dynamiques : Interfaces Sur Mesure

    - - {TEMPLATE_CONTROLLER_DYNAMIC.map(({ method, description, code }) => ( -
    -

    {method}

    -

    {description}

    - -
    - ))} - -

    - Bravo ! 🎉 Vous venez de découvrir la puissance des contrôleurs Nexy. Rappelez-vous : les fonctions en MAJUSCULES, des routes bien organisées, et vous voilà prêt à créer des applications web incroyables ! Continuez votre voyage dans la documentation pour devenir un véritable maître de Nexy. 🚀 -

    - -
    - - ← Structure - - - - Réponses → - -
    -
    - ); -} diff --git a/src/app/docs/started/new_project/page.mdx b/src/app/docs/started/new_project/page.mdx new file mode 100644 index 00000000..c471b17e --- /dev/null +++ b/src/app/docs/started/new_project/page.mdx @@ -0,0 +1,81 @@ +# Créer un projet + + + Avant de créer un projet, assurez-vous que Nexy est correctement installé.
    + Pour plus d'informations, consultez la section Installation . + Si Nexy est déjà installé sur votre système, vous pouvez continuer avec les étapes suivantes. +
    + +pour créer un projet Nexy , exécutez la commande suivante : + + + + + + + + Veillez à remplacer [ nom_du_projet ] par le nom que vous souhaitez donner à votre projet. + + +--- +## Exemple +par exemple si vous voulez créer un projet nommé test_app , vous pouvez exécuter la commande suivante : + + + + + + +Une fois que vous avez exécuté cette commande, veillez repondre aux questions qui vont s'en suivre selon vos besoin. +Vos reponses permettront à Nexy de vous génerer un projet et de le configurer selon vos besoin . + + +## Lancement du serveur de développement + +Une fois le projet créé ( test_app dans cas ) , vous pouvez le lancer en exécutant la commande suivante : + + + + + + + + + Une fois le serveur lancé, vous pouvez accéder à la documentation de l'API via l'URL suivante dans le cas d'un projet de type microservice : + http://localhost:3000/docs + +--- +## 👌 Bravo ! +Maintenant que vous avez pu créer votre projet, vous pouvez commencer à analyser sa structure !
    Nous allons voir comment faire cela dans la section suivante. + + \ No newline at end of file diff --git a/src/app/docs/started/new_project/page.tsx b/src/app/docs/started/new_project/page.tsx deleted file mode 100644 index 73129ea1..00000000 --- a/src/app/docs/started/new_project/page.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import { CodeBlock } from "@/components/CodeBlock"; -import Mark from "@/components/Mark"; -import Link from "next/link"; - -export default function InstallationPage() { - return ( -
    -

    Créer un nouveau projet

    - - - Pour démarrer avec Nexy, assurez-vous d'avoir Python 3.12 ou une version plus récente. Cette version est nécessaire pour utiliser Nexy et profiter de toutes ses fonctionnalités modernes. - - -

    1. Vérification de la version de Python

    -

    - Vérifiez que votre version de Python est à jour avec cette commande. Une version récente de Python est essentielle pour garantir la compatibilité et les meilleures performances : -

    - -

    - Si votre version de Python n'est pas à jour, téléchargez la dernière version depuis le site officiel de Python : python.org/downloads. Suivez les instructions d'installation pour votre système d'exploitation. -

    - -

    2. Installation de Nexy

    -

    - Installez Nexy avec pip, le gestionnaire de paquets Python. Nous installons aussi InquirerPy pour une meilleure interaction en ligne de commande lors de la création de projets : -

    - - -

    - Vérifiez que Nexy est correctement installé en exécutant la commande suivante. Cela vous permettra de voir la version installée et de confirmer que tout est en ordre : -

    - - -

    3. Création d'un nouveau projet Nexy

    -

    - Créez et explorez votre nouveau projet avec ces commandes. Nexy va générer automatiquement une structure de projet optimisée avec tous les fichiers nécessaires pour démarrer rapidement : -

    - - -

    4. Explorer la Structure Initiale du Projet

    -

    - Comprendre la structure initiale de votre projet est essentiel pour un développement efficace. Nexy propose deux modèles de projet principaux, chacun adapté à des besoins spécifiques. Voici un aperçu détaillé pour un projet fullstack et un projet de microservice. -

    - -

    Projet Fullstack

    -

    - La structure d'un projet fullstack gère à la fois le backend et le frontend. Cette configuration est idéale pour les applications web complètes qui nécessitent une interface utilisateur et une logique serveur intégrée. Chaque fichier a un rôle spécifique dans l'architecture : -

    - - -

    Projet Microservice

    -

    - La structure d'un projet de microservice est optimisée pour des services spécifiques et autonomes. Cette architecture est parfaite pour construire des systèmes distribués ou pour isoler des fonctionnalités spécifiques. La structure est volontairement allégée pour se concentrer sur l'essentiel : -

    - - -

    5. Lancement du serveur de développement

    -

    - Lancez le serveur de développement pour tester votre projet. Le serveur de développement de Nexy inclut le rechargement automatique du code, ce qui signifie que vos modifications seront immédiatement visibles sans avoir à redémarrer le serveur : -

    - - -

    Prochaines étapes

    -

    - Votre projet est maintenant prêt pour le développement. Pour tirer le meilleur parti de Nexy, voici quelques étapes suggérées pour continuer votre apprentissage et commencer à construire votre application : -

    -
      -
    • - Explorez la structure du projet pour vous familiariser avec les fichiers et répertoires. Prenez le temps de comprendre comment chaque composant interagit avec les autres. -
    • -
    • - Créez votre première route pour ajouter des fonctionnalités à votre application. Commencez par quelque chose de simple comme une page d'accueil ou une API basique. -
    • -
    • - Expérimentez avec les composants Nexy pour créer des interfaces utilisateur réutilisables et maintenables. -
    • -
    • - Explorez les fonctionnalités avancées comme les WebSockets et les actions serveur pour créer des applications interactives. -
    • -
    -
    - - ← Introduction - - - - Structure → - - -
    -
    - ); -} \ No newline at end of file diff --git a/src/app/docs/started/page.mdx b/src/app/docs/started/page.mdx new file mode 100644 index 00000000..eb285885 --- /dev/null +++ b/src/app/docs/started/page.mdx @@ -0,0 +1,87 @@ +# Installation + + + Nexy s'installe globalement sur votre système. Une fois installé, vous pouvez l'utiliser dans tous vos projets sans avoir à le réinstaller. + + +Avant de vouloir installer Nexy , veillez vous assurer que vous disposez d'une version de
    Python >= 3.12 +Cette vérifiaction est nécessaire pour utiliser Nexy et profiter de toutes ses fonctionnalités modernes. + +--- + + +## Comment vérifier la version de Python ? +Pour vérifier la version de Python, ouvrez votre terminal et exécutez la commande suivante : + + + + + + + + Si votre version de Python n'est pas à jour, téléchargez la dernière version depuis le site officiel de Python : + python.org/downloads . Suivez les instructions d'installation pour votre système d'exploitation. + +---- + +## Comment installer Nexy ? +Une fois que vous avez vérifié que vous disposez d'une version de Python >= 3.12, vous pouvez installer Nexy en utilisant la commande suivante : + + + + + +---- + +## Verifier Nexy est bien installe ? + +Pour vérifier que Nexy est bien installé, ouvrez votre terminal et exécutez la commande suivante : + + + + + + +---- +## 👌 Bravo ! +Maintenant que Nexy est installé, vous pouvez commencer à créer vos premiers projets !
    Nous allons voir comment faire cela dans la section suivante. + + + + diff --git a/src/app/docs/started/page.tsx b/src/app/docs/started/page.tsx deleted file mode 100644 index 3c809d03..00000000 --- a/src/app/docs/started/page.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import { CodeBlock } from "@/components/CodeBlock"; -import Mark from "@/components/Mark"; -import { Nexy } from "@/components/svg/nexy"; -import Link from "next/link"; - -export default function DocsPage() { - return ( -
    -

    - - Imaginez un monde où chaque ligne de code Python se transforme en une mélodie d'efficacité. Un univers où la puissance de FastAPI rencontre l'élégance du routing Next.js, créant une symphonie parfaite entre performance et simplicité. Cette vision n'est plus un rêve. Bienvenue dans une nouvelle ère d'excellence du développement web en Python, où chaque projet devient une aventure captivante et ultra-productive. - -

    Introduction

    -

    Le Contexte

    -

    - Dans le vaste univers du développement web en Python, les solutions se situent souvent à l'une de deux extrémités : -

    -
      -
    • - Des frameworks complets et puissants comme Django, dont la richesse se traduit parfois par une complexité qui freine l'innovation. -
    • -
    • - Des micro-frameworks agiles, à l'image de Flask, qui, malgré leur flexibilité, imposent une configuration répétitive et chronophage. -
    • -
    - -

    - FastAPI a certes révolutionné l'écosystème avec des performances inégalées et un typage moderne, mais le chemin reste semé d'embûches : -

    -
      -
    • - Une organisation de projets qui se complexifie au fil de la croissance. -
    • -
    • - Des configurations de routes répétitives, qui grignotent un temps précieux. -
    • -
    • - Des conventions de développement souvent floues, freinant une harmonisation optimale du code. -
    • -
    • - Une gestion de l'interface utilisateur qui demeure un défi pour maintenir l'agilité et l'innovation. -
    • -
    - -

    - C'est dans ce contexte que Nexy fait son entrée, prêt à redéfinir les standards du développement web en Python. Nexy combine le meilleur des mondes : l'efficacité et la robustesse de frameworks établis avec une simplicité et une flexibilité qui libèrent véritablement la créativité. Préparez-vous à transformer vos défis en opportunités et à redécouvrir le plaisir d'innover sans compromis. -

    - -

    La Vision de Nexy

    - -
    - - Nexy est né d'une réflexion profonde sur l'évolution des frameworks Python. Python brille par sa simplicité, sa puissance et son écosystème riche, mais dans le paysage actuel, Django s'impose presque comme un monopole, laissant peu de place à des alternatives comme Flask ou FastAPI. Est-ce uniquement une question de popularité, ou simplement parce qu'aucun autre framework n'offre une solution aussi complète pour le développement web moderne ? - - -

    - Django possède des fonctionnalités impressionnantes, mais sa complexité et sa lourdeur peuvent devenir un obstacle, surtout pour des projets qui n’ont pas besoin d’une telle infrastructure. Cela pose une question essentielle : pourquoi ne pas créer un framework inspiré des meilleures pratiques modernes comme dans « Next.js, NestJS ou AdonisJS » tout en préservant la simplicité et l'élégance de Python ? -

    - - - C'est cette vision qui a donné naissance à Nexy. Pensé pour offrir une expérience développeur fluide et efficace, Nexy allie la puissance asynchrone de FastAPI à une structure modulaire intuitive, réduisant la configuration au strict minimum et simplifiant la maintenance. Il transforme la complexité des configurations lourdes en une opportunité d'innovation, en restant fidèle à l'essence même de Python : simple, performant et élégant. - - -

    - Avec Nexy, vous choisissez un framework qui redéfinit les standards du développement web en Python. Concentrez-vous sur votre logique métier, sans vous laisser freiner par des contraintes techniques inutiles. -

    -
    - -

    Nos principes :

    -
      -
    • - Convention over Configuration : Adoptez des standards éprouvés dès la base. -
    • -
    • - Intuitivité : Une structure naturelle, où tout se découvre sans effort. -
    • -
    • - Productivité : Réduisez le code répétitif pour maximiser vos fonctionnalités. -
    • -
    • - Évolutivité : Du projet minimaliste à l'application d'entreprise, Nexy grandit avec vous. -
    • -
    - -

    Pourquoi Nexy ?

    - -
      -
    • - Débutants : Démarrez avec une approche fluide et intuitive, sans complexité superflue, pour apprendre Python et le développement web rapidement. -
    • -
    • - Experts : Exploitez une architecture modulaire et performante, combinant la puissance de FastAPI et la simplicité d'un routage intelligent pour des projets de grande envergure. -
    • -
    • - Tous les développeurs : Profitez d'un framework conçu pour maximiser la productivité, avec un code clair, réactif et élégant. -
    • -
    • - - Nexy, c'est bien plus qu'un simple framework : c'est une expérience de développement fluide, performante et intuitive. Libérez votre créativité, boostez votre productivité et redécouvrez le plaisir d'écrire du code efficace et élégant. - -
    • -
    - -

    Nexy : L'Aube d'une Révolution

    - - - Espoir Loém, créateur de Nexy :

    - «
    - Après des années à observer l'écosystème Python et ses frameworks, j'ai eu une révélation :
    - nous pouvions faire tellement mieux.

    - Dans notre communauté technique, Django est un excellent outil qui a fait ses preuves, mais il est temps d'innover pour répondre aux besoins modernes.

    - Je voyais de nombreux développeurs talentueux limités par des outils qui ne correspondaient plus à leurs attentes. Les fondations étaient solides, mais l'expérience développeur méritait d'être repensée.

    - C'est ainsi qu'est né Nexy, une nouvelle vision du développement web en Python. Notre objectif n'était pas simplement d'ajouter une couche d'abstraction, mais de repenser l'expérience complète du développeur.

    - Pourquoi devrions-nous choisir entre performance et simplicité ?

    - Python est un langage élégant et expressif. Il mérite des outils qui préservent sa clarté naturelle, plutôt que de la noyer dans des structures complexes.

    - Nexy incarne cette philosophie : rendre le développement web en Python aussi naturel et fluide que possible, à travers une évolution réfléchie de nos pratiques.

    - » -
    - -

    Exemple de Code

    - -

    Controller

    - - -

    Sockets

    - - - -

    Actions Serveur

    - - - - -

    Composants

    - - - -`} - /> - -

    - Une Architecture Qui Respecte Votre Intelligence 🧠 -

    - Un framework doit vous faire gagner du temps, pas vous en faire perdre. -

    - -

    - Actions Serveur : La Réalité, Pas Les Promesses 🎭 -
    - Oui, on utilise encore JavaScript en 2024. Mais on peut le faire intelligemment : -

    - -

    - Démarrage : Aussi Simple Que Prévu ⚡ -

    - -

    - Nexy est encore jeune, mais il a déjà un objectif clair : vous laisser coder en Python, proprement, sans vous prendre la tête. -
    - Envie de contribuer à un framework qui respecte ses développeurs ? Rejoignez l'aventure ! -

    - -

    - Nexy : Parce que le développement web en Python méritait mieux que des compromis constants. -

    - -
    - - Contribuer à Nexy - - - - Nouveau projet → - - -
    -
    - ); -} \ No newline at end of file diff --git a/src/app/docs/started/reponses/page.tsx b/src/app/docs/started/reponses/page.tsx deleted file mode 100644 index f00b00c2..00000000 --- a/src/app/docs/started/reponses/page.tsx +++ /dev/null @@ -1,261 +0,0 @@ -import { CodeBlock } from "@/components/CodeBlock"; -import Mark from "@/components/Mark"; -import Link from "next/link"; - -export default function ResponsesPage() { - return ( -
    -

    Gestion des Réponses HTTP avec Nexy

    - - - Nexy, construit sur FastAPI, offre une gestion avancée des réponses HTTP. Il permet d'utiliser toutes les réponses standard de FastAPI tout en ajoutant des fonctionnalités supplémentaires via le décorateur @HTTPResponse. Ce décorateur simplifie la personnalisation des réponses en encapsulant la logique de réponse dans une fonction unique. - - -

    Introduction aux Réponses HTTP

    -

    - Les réponses HTTP sont essentielles pour la communication entre le client et le serveur. Elles permettent de transmettre des données, des statuts et des en-têtes. Nexy hérite de la flexibilité de FastAPI tout en introduisant des simplifications pour une gestion plus intuitive des réponses. -

    - -

    Utilisation de la Classe Response

    -

    - La classe Response de Nexy étend celle de FastAPI, permettant une personnalisation facile des réponses : -

    - - -

    Réponses Standard de FastAPI

    -

    - Nexy supporte toutes les réponses standard de FastAPI, telles que JSONResponse, HTMLResponse, et plus encore : -

    - - -

    Personnalisation des Réponses avec HTTPResponse

    - - Le décorateur @HTTPResponse de Nexy permet de personnaliser les réponses de manière élégante et efficace. Il encapsule la logique de réponse et offre une flexibilité accrue. - - bytes: - # Logique de rendu personnalisée - data = {\n\t\t\t"data": content, \n\t\t\t"timestamp": datetime.now().isoformat()\n\t\t} - return json.dumps(data).encode("utf-8") - -@HTTPResponse(type=CustomJSONResponse) -def GET(): - return {"message": "Hello"}`} - /> - -

    HTMLResponse avec et sans Décorateur

    -

    Avec Décorateur

    -

    - Utiliser le décorateur @HTTPResponse pour enrichir votre endpoint avec une validation et une documentation automatiques : -

    - - -

    Bienvenue

    - - - """`} - /> - -

    - Avantages du décorateur : -

    -
      -
    • Documentation OpenAPI/Swagger automatique
    • -
    • Validation stricte du type de contenu
    • -
    • Gestion standardisée des erreurs
    • -
    • Meilleure maintenabilité du code
    • -
    - -

    Sans Décorateur

    -

    - Approche directe pour des cas simples : -

    - - -

    Bienvenue

    - - - """ - return HTMLResponse( - content=html_content, - status_code=200 - )`} - /> - -

    JSONResponse avec et sans Décorateur

    - - La réponse JSON est le format privilégié pour les API RESTful. Nexy facilite sa manipulation grâce à l'intégration native de Pydantic. - - -

    Avec Décorateur

    - - -

    Sans Décorateur

    - - -

    StreamingResponse avec et sans Décorateur

    -

    Avec Décorateur

    - - -

    Sans Décorateur

    - - -

    Gestion des Erreurs

    -

    - Nexy fournit des réponses d'erreur standardisées : -

    - - -

    Meilleures Pratiques pour les Réponses HTTP

    -

    - Lors de la conception de vos API avec Nexy, gardez à l'esprit les meilleures pratiques suivantes : -

    -
      -
    • Utilisez des codes de statut HTTP appropriés pour indiquer le résultat de l'opération.
    • -
    • Fournissez des messages d'erreur clairs et concis pour aider les développeurs à comprendre les problèmes.
    • -
    • Utilisez des en-têtes HTTP pour transmettre des métadonnées importantes.
    • -
    • Assurez-vous que vos réponses sont sécurisées et ne divulguent pas d'informations sensibles.
    • -
    - -
    - - ← Controllers - - - Composants → - -
    -
    - ); -} diff --git a/src/app/docs/started/structure/page.mdx b/src/app/docs/started/structure/page.mdx new file mode 100644 index 00000000..beaccbb9 --- /dev/null +++ b/src/app/docs/started/structure/page.mdx @@ -0,0 +1,147 @@ +# Structure et organisation du projet + + + Cette page fournit un aperçu des conventions de dossiers et de fichiers dans Nexy , ainsi que des conseils pour organiser votre projet de manière optimale. + + +___ + +## Conventions de dossiers +Les dossiers de niveau supérieur sont utilisés pour organiser le code et les ressources statiques de votre application. + + + + + + + + + +le dossier app est le dossier de routage d'une application Nexy +et un peu similaires à celui de Next.js ou Expo js . + +le dossier public est le dossier qui contient les ressources statiques de votre application. + +--- + +### Itinéraires imbriqués + +Les itinéraires imbriqués sont utilisés pour organiser le code et les ressources statiques de votre application. + + + + + + + + + + + + +--- + +### Itinéraires dynamiques +Un itinéraire dynamique est un itinéraire qui peut être généré à la demande. +Cela peut être utile pour générer des pages dynamiques, comme des pages de profil utilisateur ou des pages de produit. + + + + + + + + + + + + +### Dossiers privés + +Les dossiers privés sont utilisés pour organiser le code et les ressources statiques de votre application. + + + + + + + +--- +## Conventions de fichiers +Les fichiers de niveau supérieur sont utilisés pour configurer votre application, gérer les dépendances, exécuter des intergiciels, intégrer des outils de surveillance et définir des variables d'environnement. + + + + + + + + + + + + +### Fichiers de routage + +Les fichiers de routage sont utilisés pour organiser le code et les ressources statiques de votre application. + + + + + + + + +---- + +## Organiser votre projet + +Outre les conventions relatives aux dossiers et aux fichiers, +Nexy n'a pas d'opinion sur la manière dont vous organisez et regroupez les fichiers de votre projet. +Cependant, il fournit plusieurs fonctionnalités pour vous aider à organiser votre projet. + +Dans le répertoire app , des dossiers imbriqués définissent la structure de l'itinéraire. +Chaque dossier représente un segment d'itinéraire mappé à un segment correspondant dans un chemin d'URL. + + + Cependant, même si la structure de l'itinéraire est définie via des dossiers, + un itinéraire n'est pas accessible publiquement tant qu'un fichier controller.py + n'est pas ajouté à un segment d'itinéraire. + + + + + + + + + + + + + + + + + + + dkdjkjk + + + + + +## 👌 Bravo ! +Maintenant que vous avez pu créer votre projet, vous pouvez commencer à analyser sa structure !
    Nous allons voir comment faire cela dans la section suivante. + + \ No newline at end of file diff --git a/src/app/docs/started/structures/page.tsx b/src/app/docs/started/structures/page.tsx deleted file mode 100644 index 1d443c2f..00000000 --- a/src/app/docs/started/structures/page.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { CodeBlock } from "@/components/CodeBlock"; -import Mark from "@/components/Mark"; -import Link from "next/link"; - -export default function StructurePage() { - return ( -
    -

    Structure et organisation du projet

    - - - Cette page fournit un aperçu des conventions de dossiers et de fichiers dans Nexy, ainsi que des conseils pour organiser votre projet de manière optimale. - - -

    Conventions de dossiers et de fichiers

    -

    - Les dossiers de niveau supérieur sont utilisés pour organiser le code et les ressources statiques de votre application. -

    - - -

    - Les fichiers de niveau supérieur sont utilisés pour configurer votre application, gérer les dépendances, exécuter des intergiciels, intégrer des outils de surveillance et définir des variables d'environnement. -

    - - -

    Fichiers de routage

    - - -

    Itinéraires imbriqués

    - - -

    Itinéraires dynamiques

    - - -

    Dossiers privés

    - - -

    Organiser votre projet

    -

    - Outre les conventions relatives aux dossiers et aux fichiers, Nexy n'a pas d'opinion sur la manière dont vous organisez et regroupez les fichiers de votre projet. Cependant, il fournit plusieurs fonctionnalités pour vous aider à organiser votre projet. -

    - -

    Colocation

    -

    - Dans le répertoire app, des dossiers imbriqués définissent la structure de l'itinéraire. Chaque dossier représente un segment d'itinéraire mappé à un segment correspondant dans un chemin d'URL. -

    - -

    - Cependant, même si la structure de l'itinéraire est définie via des dossiers, un itinéraire n'est pas accessible publiquement tant qu'un fichier controller.py n'est pas ajouté à un segment d'itinéraire. -

    - - - - -

    - Et, même lorsqu'un itinéraire est rendu accessible au public, seul le contenu renvoyé par controller.py est envoyé au client. -

    - - - - -

    Exemple de structure de projet

    -

    - L'architecture de base d'un projet Nexy est une symphonie d'organisation, orchestrée pour maximiser la clarté et l'efficacité de votre code. Voici un exemple de cette structure harmonieuse et bien pensée : -

    - - - -
      -
    • - Familiarisez-vous avec la structure du projet pour bien comprendre l'organisation des fichiers et répertoires. Prenez le temps d'analyser comment chaque composant interagit avec les autres. -
    • -
    • - Concevez votre première route pour ajouter des fonctionnalités à votre application. Commencez par une tâche simple, comme une page d'accueil ou une API basique. -
    • -
    • - Expérimentez avec les composants Nexy pour créer des interfaces utilisateur réutilisables et maintenables. -
    • -
    • - Explorez les fonctionnalités avancées telles que les WebSockets et les actions serveur pour développer des applications interactives. -
    • -
    -
    - - ← nouveau projet - - - - Controllers → - - -
    -
    - ); -} diff --git a/src/app/docs/started/template.tsx b/src/app/docs/started/template.tsx index 7623ab95..9e97e07d 100644 --- a/src/app/docs/started/template.tsx +++ b/src/app/docs/started/template.tsx @@ -1,24 +1,12 @@ -"use client" -import { motion } from "framer-motion"; -import React, { ReactNode } from 'react'; +import { TemplateEffect } from "@/components/(home)/docs/templateEffect"; -interface TemplateProps { - children: ReactNode; +type TemplateProps = { + children: React.ReactNode; } +const Template = ({ children }: TemplateProps) => ( + + {children} + +) -const Template = ({ children }: TemplateProps) => { - return ( - - {children} - - - ); -}; - -export default Template; +export default Template \ No newline at end of file diff --git a/src/app/docs/started/views/page.tsx b/src/app/docs/started/views/page.tsx deleted file mode 100644 index f6a00674..00000000 --- a/src/app/docs/started/views/page.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { CodeBlock } from "@/components/CodeBlock"; -import Mark from "@/components/Mark"; -import Link from "next/link"; - -export default function ViewsPage() { - return ( -
    -

    View

    - -
    - - Dans Nexy, une view est un composant essentiel qui se trouve dans le fichier controller.py. Elle joue un rôle crucial en structurant et en présentant les données de manière claire et esthétique, facilitant ainsi l'interaction utilisateur. Les views permettent de lier la logique métier à la présentation, offrant une expérience utilisateur fluide et intuitive. - -
    - -
    -

    Structure du dossier pour une view


    - -
    - -
    -

    Comment définir une view

    -

    - Une view dans Nexy est une fonction Python enrichie par le décorateur @component. Elle intègre la logique métier et la présentation pour générer des pages web interactives et dynamiques. En utilisant des views, vous pouvez encapsuler des fonctionnalités complexes tout en gardant le code organisé et maintenable. -


    - -
    - -
    -

    Exploiter une view

    -

    - Une fois créée, une view peut être utilisée pour afficher des données de manière structurée. Par exemple, une view de profil utilisateur peut intégrer divers composants pour présenter les détails de l'utilisateur de façon cohérente. Cela permet de créer des interfaces utilisateur qui sont à la fois esthétiques et fonctionnelles, en tirant parti de la puissance des composants réutilisables. -


    - \n \n \n`} - /> -
    - -
    -

    Pourquoi utiliser des views ?

    -

    - L'utilisation des views offre de nombreux avantages : -

    -
      -
    • Code bien organisé et facile à comprendre, ce qui facilite la collaboration entre les développeurs.
    • -
    • Réutilisation efficace des composants, permettant de réduire la duplication de code et d'améliorer la cohérence de l'application.
    • -
    • Maintenance simplifiée grâce à une structure modulaire, rendant les mises à jour et les modifications plus faciles à gérer.
    • -
    • Possibilité de créer des pages web dynamiques et interactives, offrant une expérience utilisateur enrichie et engageante.
    • -
    -
    - -
    - - ← Composants - - - Server actions → - -
    -
    - ); -} diff --git a/src/app/docs/template.tsx b/src/app/docs/template.tsx deleted file mode 100644 index 8e70b38a..00000000 --- a/src/app/docs/template.tsx +++ /dev/null @@ -1,24 +0,0 @@ -"use client" -import { motion } from "framer-motion"; -import React, { ReactNode } from 'react'; - -interface TemplateProps { - children: ReactNode; -} - -const Template = ({ children }: TemplateProps) => { - return ( - - {children} - - - ); -}; - -export default Template; diff --git a/src/app/docs/testing/[...slug]/page.mdx b/src/app/docs/testing/[...slug]/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/testing/page.tsx b/src/app/docs/testing/page.tsx new file mode 100644 index 00000000..9559d558 --- /dev/null +++ b/src/app/docs/testing/page.tsx @@ -0,0 +1,9 @@ +const TestingPage = () => { + return ( +
    +

    Testing Page

    +
    + ); +}; + +export default TestingPage; diff --git a/src/app/docs/views/[...slug]/page.mdx b/src/app/docs/views/[...slug]/page.mdx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/docs/views/page.tsx b/src/app/docs/views/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/globals.css b/src/app/globals.css index 4dcaf99c..648291a6 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,22 +1,96 @@ @import "tailwindcss"; +/* @plugin "@tailwindcss/typography"; */ @source "../src/**/*.{js,ts,jsx,tsx,md}"; @source "../src/components*.{js,ts,jsx,tsx,md}"; /* Ajouter des variables CSS */ :root { - --primary-color: #A9FFEA; - --background: color-mix(in srgb, #040807 60%, #0D1713 40%); + + --primary-color: rgb(168, 255, 233); + --background: color-mix(in srgb, hsl(165, 33%, 2%) 60%, hsl(156, 28%, 7%) 40%); + --foreground : hsl(0, 0%, 96%); + + @media (prefers-color-schem: light){ + --primary-color: hsl(150, 58%, 40%); + --background: color-mix(in srgb, hsl(155, 20%, 84%) 60%, #EDEFF2 40%); + --foreground: hsl(164, 92%, 5%); + } } -body { - /* background-color: #040807; */ - /* background-color: #0D1713; */ - - background: var(--background); - color: #F6F6F6; -} +@custom-variant dark (&:where(.dark, .dark *)); @theme { --color-background: var(--background); + --color-primary: var(--primary-color); + --color-foreground: var(--foreground); +} + +@layer base { + + * { + @apply outline-0; + } + body{ + @apply bg-background text-foreground dark:bg-amber-100; + } + *:not(hr, .notscroll) { + scrollbar-width: thin; + scrollbar-color: #e6f3eaa6 transparent; + scrollbar-gutter: stable; + + @media (prefers-color-scheme: light) { + scrollbar-color: #66696778 transparent; + + } + + } + + .mdx { + & h1 { + @apply text-4xl font-semibold mb-2; + } + & h2 { + @apply text-2xl font-semibold; + } + & h3{ + @apply text-lg font-medium ; + } + & p{ + @apply leading-[170%] opacity-85 ; + } + + & hr{ + @apply border-gray-50/15 border-dotted my-5; + } + & ul:not(.folder){ + @apply flex flex-col gap-1; + } + & li:not(.file,.line) { + @apply flex items-center gap-2 text-gray-50/70 text-sm; + } + + + + + } +} + +@layer components { + .active-link { + @apply text-yellow-300 relative flex items-center gap-2; + + &::before { + content: ''; + @apply border-l-2 h-5 rounded-4xl border-yellow-300/50 inline absolute -translate-x-3 left-[-1px]; + } + } + + .collapse { + /* -o-animation: ; */ + } + .header { + /* */ + } + } \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 1aa6414d..9cb25e2c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,16 +1,12 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { Analytics } from "@vercel/analytics/react" import "./globals.css"; - -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); +import { inter, jetbrainsMono } from "@/font/google"; +import { Header } from "@/components/(home)/header"; +import { Footer } from "@/components/(home)/footer"; +import { LightDark } from "@/components/(home)/lightDark"; +import { Language } from "@/components/(home)/language"; +import { MenuModal } from "@/components/(home)/menu.modal"; export const metadata: Metadata = { title: "Nexy", @@ -25,15 +21,37 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + - + - {children} + +
    +
    +
    + {children} +
    + +