NetovaTodo – Bezpieczna aplikacja zadań, która zaufanie buduje kodem
95+/100
Performance
100/100
SEO Score
100/100
Accessibility
AES-256
security
2 OAuth
authProviders
0.6s
Czas ładowania

Galeria
Wyzwanie projektu
NetovaTodo to nasz własny projekt demonstracyjny — produkcyjna aplikacja SaaS do zarządzania zadaniami, która pokazuje naszym klientom, że potrafimy budować nie tylko strony wizytówkowe, ale pełnoprawne aplikacje webowe z autoryzacją, bazą danych i zaawansowanym bezpieczeństwem.
Wymagania były jasne i niecompromisowe:
„Aplikacja musi być bezpieczna od pierwszej linii kodu. Każde zadanie użytkownika zaszyfrowane, każde wejście zwalidowane, żadna informacja nie może wyciec. Ma działać jak szwajcarski zegarek na każdym urządzeniu."
Główne wymagania
- Bezpieczeństwo na pierwszym miejscu — dane zadań szyfrowane AES-256 po stronie serwera, nie w przeglądarce
- OAuth zamiast haseł — brak tradycyjnych loginów i haseł eliminuje cały wektor ataków credential stuffing
- Serverless od zera — zero kosztów hostingu bazy danych przy małym ruchu, automatyczne skalowanie
- Mobile-first UX — ponad 70% ruchu aplikacji pochodzi z urządzeń mobilnych
- Dark mode — obowiązkowy w aplikacjach SaaS skierowanych do developerów i technicznej grupy docelowej
- Rate limiting — ochrona przed nadużyciami bez zewnętrznych usług (Redis), bazując na pamięci in-memory
Nasze podejście
Projekt realizowaliśmy jako wewnętrzny showcase — żadnych kompromisów, każda decyzja techniczna uzasadniona.
1. Architektura bezpieczeństwa (Dni 1–4)
Bezpieczeństwo nie jest tu przysłowiowym komentarzem na końcu README. To fundament, od którego zaczyna się każda warstwa aplikacji.
Model zagrożeń, który zaadresowaliśmy:
- Eksfiltracja danych z bazy → szyfrowanie AES-256 po stronie serwera przed zapisem
- Kradzież sesji → JWT z krótkim TTL,
httpOnly,secure,sameSite=strictcookies przez NextAuth - Credential stuffing → brak tradycyjnych haseł; wyłącznie OAuth (Google, GitHub)
- Injection attacks → walidacja każdego inputu przez Zod; baza SQL przez parametryzowane zapytania libSQL
- Rate abuse → in-memory rate limiter per
userId:action— 30 akcji/60 s na użytkownika - CSRF → wbudowana ochrona Next.js Server Actions + CSRF token w formularzach
- Data leakage w URL → IDs zadań jako liczby całkowite, nie UUID; route
/bez identyfikatorów wrażliwych
2. Baza danych — Turso (serverless SQLite) (Dni 5–8)
Wybór bazy danych to jedna z ważniejszych decyzji architektonicznych. Wybraliśmy Turso z czterech powodów:
- Kompatybilność z SQLite — zero vendor lock-in; można zmienić na lokalny plik
.dbw każdej chwili - Serverless z edge replication — latencja poniżej 5 ms z Europy dzięki globalnej sieci edge nodes
- Darmowy tier — 5 GB storage, 500 milionów row reads miesięcznie — wystarczy na produkcję
- Driver
@libsql/client— oficjalny driver z pełnym TypeScript API, typowane zapytania
Struktura tabeli:
┌──────────────────────────────────────────────────┐
│ todos │
├──────────────┬───────────────────────────────────┤
│ id │ INTEGER PRIMARY KEY AUTOINCREMENT │
│ userId │ TEXT NOT NULL │
│ taskName │ TEXT NOT NULL (AES-256) │
│ taskFinished │ NUMERIC DEFAULT 0 │
│ dueDate │ TEXT │
│ createdAt │ NUMERIC DEFAULT CURRENT_TIMESTAMP │
└──────────────┴───────────────────────────────────┘
Pole taskName przechowuje wyłącznie zaszyfrowany ciąg AES-256 — nawet administrator bazy danych bez klucza szyfrowania nie odczyta treści zadań.
3. Autoryzacja — NextAuth v5 (Dni 9–12)
Wybraliśmy NextAuth v5 ([email protected]) — najnowszą generację biblioteki, zoptymalizowaną dla Next.js App Router.
Konfiguracja:
- Strategia JWT — sesje bezstanowe; serwer nie przechowuje tokenów, JWT odnawiany przy każdym żądaniu
- Dostawcy: Google OAuth 2.0 + GitHub OAuth — dwaj najpopularniejsi wśród grupy docelowej
- Stable User ID — generujemy stabilne ID z
account.providerAccountId, nie ztoken.sub; to kluczowe dla integralności danych między loginami - Middleware ochrony tras —
middleware.tssprawdza sesję przed renderem strony; unauthenticated redirect do/login - Potwierdzenie wylogowania — modal z Framer Motion; wylogowanie wymaga potwierdzenia i zatrzymuje scroll strony (bez migotania layout shift)
4. Rozwój (Dni 13–21)
Stack technologiczny:
- Next.js 16 (App Router) — Server Actions jako API; zero osobnego backendu, zero Express; wszystkie mutacje danych przez
"use server"funkcje - React 19 — concurrent features, Actions w formularzach,
useOptimisticdla natychmiastowego UI feedback - Tailwind CSS 4 — utility-first; zero zbędnych klas; idealne Core Web Vitals
- TypeScript 5 — pełne typowanie end-to-end; błędy wychwytywane w IDE, nie na produkcji
- Framer Motion 12 — animacje modala wylogowania (
AnimatePresence+ spring), płynne wejście listy zadań - Zod 4 — walidacja po stronie serwera każdego inputu; schema
taskNameSchema(max 500 znaków),dueDateSchema(format ISO),idSchema(walidacja typów) - date-fns — formatting dat; lekka biblioteka (tree-shaking), zero moment.js
- sonner — toast notifications; lekkie, dostępne, iOS-like design
- use-debounce — debouncing wyszukiwarki zadań; brak zbędnych zapytań przy wpisywaniu
- react-icons — tylko używane ikony (tree-shaking przez
optimizePackageImports) - next-themes — dark mode bez FOUC (Flash of Unstyled Content); motyw persystowany w
localStorage - Vercel — edge hosting, automatyczne deploye z GitHub, zero konfiguracji
Kluczowe decyzje techniczne:
- Server Actions bez API routes — mutacje przez
"use server"eliminują osobny endpoint API; SEO-friendly, mniejszy bundle klienta revalidatePathpo każdej mutacji — ISR-style cache invalidation; UI zawsze aktualnyunstable_noStore— wyłączenie cache dla odczytu zadań; każde wczytanie pobiera świeże daneuseCallbacknarefreshTodos— memoizacja callbacków odświeżania; zero zbędnych re-renderów- Focus management w modal — po otwarciu modala focus przenosi się na przycisk potwierdzenia (
autoFocus); nawigacja klawiaturą działa poprawnie
5. Architektura komponentów
| Komponent | Odpowiedzialność |
| ------------- | ----------------------------------------------------------------------------- |
| Navbar | Awatar, imię użytkownika, przycisk wylogowania; fixed top z glassmorphism |
| Greeting | Dynamiczny pozdrowienie zależne od pory dnia (dzień dobry / dobry wieczór) |
| AddTodo | Formularz dodawania z datą, walidacją i debounce; Server Action pod spodem |
| TodoList | Wirtualizowana lista; animacje wejścia Framer Motion; pusta skrzynka state |
| TodoItem | Checkbox, tekst (odszyfrowany), data, usuwanie; optymistyczny update UI |
| Search | Debounced search przez `use-debounce`; filtruje po stronie klienta |
| LogoutModal | AnimatePresence modal; blokuje scroll bez scroll lock race condition |
| ThemeToggle | next-themes; sun/moon icon; zero FOUC dzięki suppressHydrationWarning |
6. Bezpieczeństwo — szczegóły implementacji
Szyfrowanie AES-256:
Przepływ danych:
User input → Zod validation → AES-256 encrypt (server) → Turso DB
Turso DB → fetch → AES-256 decrypt (server) → React component
Klucz szyfrowania przechowywany wyłącznie w process.env.ENCRYPTION_KEY — nigdy nie trafia do klienta. Moduł encryption.ts używa crypto-js z losowym IV (initialization vector) per każde szyfrowanie.
Rate limiting:
const ACTION_WINDOW = 60 * 1000; // 60 sekund
const ACTION_MAX = 30; // 30 akcji / 60 sekund / użytkownik
Limity osobne per {userId}:{action} — flood na jednym koncie nie blokuje innych użytkowników.
Architektura wdrożenia
GitHub → Vercel CI/CD → Edge Network
↓
Next.js 16 (Vercel)
↓
Turso (edge SQLite)
Zero infra do zarządzania. Zero cold startów na Vercel Edge. Automatyczny SSL. Deploy przy każdym git push main.
Wyniki
| Metryka | Wartość | Standard branżowy |
| ---------------------------- | ------------- | ----------------- |
| Lighthouse Performance | 95+ | >90 |
| Lighthouse SEO | 100 | 100 |
| Lighthouse Accessibility | 100 | >90 |
| Czas ładowania (LCP) | 0.6 s | <2.5 s |
| Szyfrowanie danych | AES-256 | Standard bankowy |
| Providerzy OAuth | 2 (Google/GH) | — |
| Cold start Vercel Edge | <50 ms | — |
| Rate limit per user | 30 req/min | Ochrona produkcji |
Co wyróżnia ten projekt
NetovaTodo to więcej niż przykładowe CRUD. To proof-of-concept produkcyjnej aplikacji SaaS, który demonstruje naszym klientom:
- Bezpieczeństwo by design — szyfrowanie i autoryzacja nie są "do dodania później"; to fundament
- Zero backend overhead — Next.js Server Actions jako warstwy API; jeden deploy, jedna platforma
- Serverless-first — Turso + Vercel = zero kosztów operacyjnych dla małego i średniego ruchu
- Developer experience — TypeScript end-to-end, Zod validation, ESLint; kod gotowy na skalowanie
Chcesz aplikacji webowej z podobnymi standardami bezpieczeństwa i wydajności? Skontaktuj się z nami — przygotujemy darmową wycenę w 24h.
Chcesz podobnych wyników?
Skontaktuj się z nami — przygotujemy darmową wycenę w 24h.