+
Tripoli Cloud — 2026
Hébergé sur votre propre serveur
Sans publicité, sans traçage
diff --git a/app/src/components/auth/Doodle.tsx b/app/src/components/auth/Doodle.tsx
deleted file mode 100644
index 63b0333..0000000
--- a/app/src/components/auth/Doodle.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-/** Petits traits dessinés à la main, en accent décoratif - inspirés du
- * ton "studiocart.co" : jamais informatifs, purement une touche humaine
- * dans une interface par ailleurs très structurée. */
-export function DoodleSquiggle({ className }: { className?: string }) {
- return (
-
-
-
- );
-}
-
-export function DoodleArrow({ className }: { className?: string }) {
- return (
-
-
-
-
- );
-}
diff --git a/app/src/components/layout/TopBar.tsx b/app/src/components/layout/TopBar.tsx
index 70701cb..82f685c 100644
--- a/app/src/components/layout/TopBar.tsx
+++ b/app/src/components/layout/TopBar.tsx
@@ -1,11 +1,9 @@
-import { Menu, Moon, Search, Sun } from 'lucide-react';
-import { useTheme } from '../../contexts/ThemeContext';
+import { Menu, Search } from 'lucide-react';
import { useNavigation } from '../../contexts/NavigationContext';
import { useIsMobile } from '../../hooks/useIsMobile';
import { NotificationCenter } from '../notifications/NotificationCenter';
export function TopBar() {
- const { theme, toggleTheme } = useTheme();
const { openDrawer } = useNavigation();
const isMobile = useIsMobile();
@@ -32,14 +30,6 @@ export function TopBar() {
-
- {theme === 'dark' ? : }
-
diff --git a/app/src/components/layout/TripoliLogo.tsx b/app/src/components/layout/TripoliLogo.tsx
index c3b7afa..da281bf 100644
--- a/app/src/components/layout/TripoliLogo.tsx
+++ b/app/src/components/layout/TripoliLogo.tsx
@@ -5,8 +5,8 @@ interface TripoliLogoProps {
/** Minimalist inline SVG mark — no external asset, easy to swap later. */
export function TripoliLogo({ size = 28, variant = 'sidebar' }: TripoliLogoProps) {
- const badgeFill = variant === 'hero' ? 'rgba(23,20,14,0.05)' : 'rgba(91,140,255,0.14)';
- const badgeStroke = variant === 'hero' ? 'rgba(23,20,14,0.16)' : 'rgba(91,140,255,0.36)';
+ const badgeFill = variant === 'hero' ? 'rgba(255,255,255,0.12)' : 'rgba(91,140,255,0.14)';
+ const badgeStroke = variant === 'hero' ? 'rgba(255,255,255,0.28)' : 'rgba(91,140,255,0.36)';
return (
diff --git a/app/src/contexts/ThemeContext.tsx b/app/src/contexts/ThemeContext.tsx
deleted file mode 100644
index 9696092..0000000
--- a/app/src/contexts/ThemeContext.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { createContext, useContext, useEffect, useState, type ReactNode } from 'react';
-import type { Theme } from '../types';
-
-interface ThemeContextValue {
- theme: Theme;
- toggleTheme: () => void;
-}
-
-const ThemeContext = createContext(null);
-
-/**
- * Dark/light is kept in React state only — intentionally not persisted to
- * localStorage. It's applied as Tailwind's `dark` class on , so
- * `dark:` utilities and the CSS-variable tokens in index.css move together.
- */
-export function ThemeProvider({ children }: { children: ReactNode }) {
- const [theme, setTheme] = useState('light');
-
- useEffect(() => {
- document.documentElement.classList.toggle('dark', theme === 'dark');
- }, [theme]);
-
- const toggleTheme = () => setTheme((t) => (t === 'dark' ? 'light' : 'dark'));
-
- return {children} ;
-}
-
-export function useTheme(): ThemeContextValue {
- const ctx = useContext(ThemeContext);
- if (!ctx) throw new Error('useTheme must be used within a ThemeProvider');
- return ctx;
-}
diff --git a/app/src/hooks/useBackgroundCrossfade.ts b/app/src/hooks/useBackgroundCrossfade.ts
index ba17ca6..6a0307d 100644
--- a/app/src/hooks/useBackgroundCrossfade.ts
+++ b/app/src/hooks/useBackgroundCrossfade.ts
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
-import { BACKGROUND_SCENES } from '../lib/backgrounds';
+import { BACKGROUND_PHOTOS } from '../lib/backgrounds';
-const INTERVAL_MS = 8000;
+const INTERVAL_MS = 9000;
export function useBackgroundCrossfade(): number {
const [index, setIndex] = useState(0);
@@ -9,7 +9,7 @@ export function useBackgroundCrossfade(): number {
useEffect(() => {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const id = window.setInterval(() => {
- setIndex((i) => (i + 1) % BACKGROUND_SCENES.length);
+ setIndex((i) => (i + 1) % BACKGROUND_PHOTOS.length);
}, INTERVAL_MS);
return () => window.clearInterval(id);
}, []);
diff --git a/app/src/index.css b/app/src/index.css
index ac69d4c..d13e2d2 100644
--- a/app/src/index.css
+++ b/app/src/index.css
@@ -5,14 +5,10 @@
@tailwind utilities;
/*
- * Theme tokens consumed by tailwind.config.js (colors.bg, colors.panel, ...).
- * `.dark` is toggled on by ThemeContext — this is what makes
- * Tailwind's `dark:` strategy and these variables move together.
- *
- * Thème clair "éditorial" par défaut (papier + encre + citron vert en
- * accent) plutôt que le coffre-fort sombre d'origine - inspiré du ton
- * studiocart.co : gros titres serif, cartes blanches nettes, un seul
- * accent vif utilisé avec parcimonie plutôt que des néons partout.
+ * Jetons de thème consommés par tailwind.config.js (colors.bg, colors.panel, ...).
+ * Un seul thème, volontairement : pas de bascule clair/sombre - une
+ * direction visuelle assumée plutôt que deux expériences à maintenir.
+ * Papier + encre + citron vert en accent unique, sourd et rare.
*/
:root {
--tc-bg: #faf7f1;
@@ -26,18 +22,6 @@
--tc-shadow: 0 20px 48px rgba(23, 20, 14, 0.09);
}
-:root.dark {
- --tc-bg: #0a0c11;
- --tc-panel: rgba(255, 255, 255, 0.045);
- --tc-panel-2: rgba(255, 255, 255, 0.075);
- --tc-line: rgba(255, 255, 255, 0.09);
- --tc-field: rgba(255, 255, 255, 0.05);
- --tc-selected: rgba(91, 140, 255, 0.16);
- --tc-ink: #eef1f7;
- --tc-ink-2: rgba(238, 241, 247, 0.56);
- --tc-shadow: 0 28px 60px rgba(0, 0, 0, 0.5);
-}
-
html,
body,
#root {
diff --git a/app/src/lib/backgrounds.ts b/app/src/lib/backgrounds.ts
index f013712..c4b90a7 100644
--- a/app/src/lib/backgrounds.ts
+++ b/app/src/lib/backgrounds.ts
@@ -1,49 +1,43 @@
/**
- * Scènes du diaporama de fond de l'écran de connexion : art génératif
- * (pas de photo tierce, pour rester libre de droits) - de larges taches de
- * couleur pastel, floutées, qui dérivent lentement (voir `.tc-drift` dans
- * index.css) et s'enchaînent en fondu. Palette "papier + pastel", assortie
- * au thème éditorial clair du reste de l'interface.
+ * Photos du diaporama de fond de l'écran de connexion — hotlinkées
+ * directement depuis Unsplash (jamais téléchargées/réhébergées), comme
+ * l'exige leur charte développeur. Chaque photo garde l'attribution du
+ * photographe (nom + lien), affichée en bas de l'écran de connexion.
+ * Sélection à la main via l'API Unsplash (recherche "architecture
+ * minimaliste", "zen", "brume montagne") - le déclenchement de
+ * l'endpoint /download a été fait une fois au moment du choix, comme
+ * demandé par les règles d'usage de l'API.
*/
-export interface BackgroundBlob {
- color: string;
- top: string;
- left: string;
- size: string;
-}
-
-export interface BackgroundScene {
+export interface BackgroundPhoto {
id: string;
- base: string;
- blobs: BackgroundBlob[];
+ url: string;
+ photographerName: string;
+ photographerUrl: string;
}
-export const BACKGROUND_SCENES: BackgroundScene[] = [
+export const BACKGROUND_PHOTOS: BackgroundPhoto[] = [
{
- id: 'lavande',
- base: 'linear-gradient(160deg, #f4efe6 0%, #efe9de 55%, #eae3d6 100%)',
- blobs: [
- { color: 'rgba(196,181,253,0.55)', top: '-16%', left: '55%', size: '58vw' },
- { color: 'rgba(253,186,203,0.42)', top: '48%', left: '-8%', size: '50vw' },
- { color: 'rgba(200,255,82,0.28)', top: '64%', left: '62%', size: '36vw' },
- ],
+ id: 'ak5R4Y7MkW8',
+ url: 'https://images.unsplash.com/photo-1619857121838-997e82345250?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&q=80&w=1920',
+ photographerName: 'Rufat Mammadov',
+ photographerUrl: 'https://unsplash.com/@rufatmammadov?utm_source=tripoli_cloud&utm_medium=referral',
},
{
- id: 'peche',
- base: 'linear-gradient(160deg, #f6efe4 0%, #f1e9db 55%, #ece1d0 100%)',
- blobs: [
- { color: 'rgba(255,196,158,0.5)', top: '-12%', left: '64%', size: '56vw' },
- { color: 'rgba(255,150,164,0.34)', top: '52%', left: '6%', size: '48vw' },
- { color: 'rgba(196,181,253,0.26)', top: '6%', left: '4%', size: '34vw' },
- ],
+ id: 'n-hTpYafJQA',
+ url: 'https://images.unsplash.com/photo-1503450843813-359b7b07bd36?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&q=80&w=1920',
+ photographerName: 'Raychan',
+ photographerUrl: 'https://unsplash.com/@wx1993?utm_source=tripoli_cloud&utm_medium=referral',
},
{
- id: 'menthe',
- base: 'linear-gradient(160deg, #eef2e6 0%, #eaeee0 55%, #e4e8d8 100%)',
- blobs: [
- { color: 'rgba(167,229,180,0.5)', top: '4%', left: '68%', size: '52vw' },
- { color: 'rgba(140,214,214,0.4)', top: '58%', left: '-6%', size: '54vw' },
- { color: 'rgba(200,255,82,0.24)', top: '70%', left: '66%', size: '34vw' },
- ],
+ id: '7AM9xVtFlZ0',
+ url: 'https://images.unsplash.com/photo-1673295716958-b1dc96e5b24f?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&q=80&w=1920',
+ photographerName: 'Nicolas Solerieu',
+ photographerUrl: 'https://unsplash.com/@slrncl?utm_source=tripoli_cloud&utm_medium=referral',
+ },
+ {
+ id: 'SpzGTdBg738',
+ url: 'https://images.unsplash.com/photo-1529333110658-26b4cf759641?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&q=80&w=1920',
+ photographerName: 'Dave Hoefler',
+ photographerUrl: 'https://unsplash.com/@iamthedave?utm_source=tripoli_cloud&utm_medium=referral',
},
];
diff --git a/app/src/types.ts b/app/src/types.ts
index deba3e6..697499c 100644
--- a/app/src/types.ts
+++ b/app/src/types.ts
@@ -99,4 +99,3 @@ export type AppView = 'auth' | 'app';
export type NavKey = 'dashboard' | 'photos' | 'backups' | 'settings';
export type AuthMode = 'login' | 'signup';
export type FileFilter = 'Tous' | 'Documents' | 'Médias';
-export type Theme = 'light' | 'dark';
diff --git a/app/tailwind.config.js b/app/tailwind.config.js
index fc2669b..ad72c86 100644
--- a/app/tailwind.config.js
+++ b/app/tailwind.config.js
@@ -1,16 +1,12 @@
/**
* Design tokens for Tripoli Cloud, centralized here so components never
- * hardcode colors, radii or spacing inline. Values mirror the validated
- * Claude Design prototype (`project/Tripoli Cloud.dc.html`).
+ * hardcode colors, radii or spacing inline.
*
- * Surface/text colors resolve through CSS variables (see src/index.css) so
- * the same class (e.g. `bg-panel`) renders correctly in both themes without
- * a `dark:` variant on every element. Theme switching itself still goes
- * through Tailwind's `dark` class strategy on .
+ * Surface/text colors resolve through CSS variables (see src/index.css) -
+ * a single theme, deliberately: no dark/light toggle to maintain.
* @type {import('tailwindcss').Config}
*/
export default {
- darkMode: 'class',
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {