Compare commits

...
8 Commits
7 changed files with 77 additions and 6 deletions

No files matched your search

+12 -1
View File
@@ -54,9 +54,20 @@ pnpm install
### Build et exécution locale
Avec Docker Compose (recommandé) :
```bash
docker compose up -d
```
Le port peut être changé via la variable d'environnement `PORT` (par défaut 8080) :
`PORT=9090 docker compose up -d`.
Ou avec les commandes Docker :
```bash
docker build -t notes .
docker run -d --name notes -p 8080:80 notes
docker run -d --rm --name notes -p 8080:80 notes
```
L'app sera accessible sur http://localhost:8080.
+8
View File
@@ -0,0 +1,8 @@
services:
notes:
build: .
image: notes
container_name: notes
restart: unless-stopped
ports:
- "${PORT:-8080}:80"
+52
View File
@@ -0,0 +1,52 @@
# Notes
Application de prise de notes personnelle sous forme de SPA PWA (React + TypeScript + Tailwind CSS).
Installable, utilisable hors connexion, et 100 % privée : les données restent dans le **localStorage** du navigateur, sans partage ni transmission à un serveur externe.
## Fonctionnalités
- Créer, lire, modifier et supprimer des notes
- Données stockées localement (localStorage) — aucune donnée partagée ni transmise
- PWA installable avec mode hors connexion
- Design responsive mobile-first
- Modale RGPD, confirmation avant suppression, page d'erreur 404
## Utilisation
L'image est servie par nginx et exposée sur le port 80.
### Docker
```bash
docker run -d --rm --name notes -p 8080:80 devcodetools/notes:latest
```
Accédez ensuite à l'application sur http://localhost:8080.
### Docker Compose
```yaml
services:
notes:
image: devcodetools/notes:latest
container_name: notes
restart: unless-stopped
ports:
- "8080:80"
```
Puis :
```bash
docker compose up -d
```
## Construction depuis les sources
```bash
docker build -t devcodetools/notes:latest .
```
## Confidentialité
Vos notes ne quittent jamais votre appareil : stockage uniquement dans le localStorage de votre navigateur, aucune donnée partagée avec des tiers, aucune transmission vers un serveur.
+1 -1
View File
@@ -39,7 +39,7 @@ function App() {
}
return (
<main className="mx-auto flex w-full max-w-2xl min-h-dvh flex-col pb-[calc(env(safe-area-inset-bottom)+7rem)]">
<main className="mx-auto flex w-full max-w-3xl min-h-dvh flex-col pb-[calc(env(safe-area-inset-bottom)+7rem)]">
<header className="sticky top-0 z-10 border-b border-gray-200 bg-white/95 px-4 pb-3 pt-[calc(env(safe-area-inset-top)+0.75rem)] backdrop-blur">
<div className="flex h-11 items-center gap-1">
{creating || selectedNote ? (
+1 -1
View File
@@ -6,7 +6,7 @@ function ErrorPage({
message = "Désolé, la page que vous cherchez n'existe pas.",
}: ErrorPageProps) {
return (
<main className="mx-auto flex w-full max-w-2xl min-h-dvh flex-col items-center justify-center gap-6 px-4 text-center">
<main className="mx-auto flex w-full max-w-3xl min-h-dvh flex-col items-center justify-center gap-6 px-4 text-center">
<p className="text-6xl font-bold text-blue-700">{code}</p>
<div>
<h1 className="text-2xl font-semibold">{title}</h1>
+1 -1
View File
@@ -13,7 +13,7 @@ describe('RgpdInfo', () => {
render(<RgpdInfo open onClose={vi.fn()} />)
expect(screen.getByRole('dialog', { name: 'Protection des données (RGPD)' })).toBeInTheDocument()
expect(screen.getByText('localStorage', { exact: false })).toBeInTheDocument()
expect(screen.getByText(/stockage local/i)).toBeInTheDocument()
expect(
screen.getByText(/ne sont jamais partagées avec des tiers/i),
).toBeInTheDocument()
+2 -2
View File
@@ -11,8 +11,8 @@ export default defineConfig({
registerType: 'autoUpdate',
includeAssets: ['icon.svg', 'apple-touch-icon-180x180.png'],
manifest: {
name: 'new',
short_name: 'new',
name: 'Notes',
short_name: 'Notes',
description: 'Application web SPA PWA installable et utilisable hors connexion.',
lang: 'fr',
start_url: '/',