Pomiń do treści
Netova
← Wszystkie realizacje

NetovaTodo – Bezpieczna aplikacja zadań, która zaufanie buduje kodem

Plan Pro / Custom🔗 Zobacz stronę na żywo
Next.jsTursoNextAuthWebAuthnPasskeysPWAAES-256Framer MotionPerformance

95+/100

Performance

100/100

SEO Score

100/100

Accessibility

AES-256 & WebAuthn

security

Passkeys + 2 OAuth

authProviders

0.6s

Czas ładowania

NetovaTodo – Bezpieczna aplikacja zadań, która zaufanie buduje kodem

Galeria

Widok główny – lista zadań z dark mode
Ekran logowania – biometryczne Passkeys i OAuth
Web Vitals NetovaTodo – mobile
Web Vitals NetovaTodo – desktop

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 niekompromisowe:

„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
  • Pełny ekosystem passwordless — wdrożenie Passkeys (WebAuthn) eliminujących phishing, wyciek haseł i konieczność zapamiętywania danych logowania
  • 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=strict cookies przez NextAuth
  • Credential stuffing → brak tradycyjnych haseł; wyłącznie OAuth i Passkeys
  • 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

Dodatkowo wdrożyliśmy WebAuthn (Passkeys) zintegrowane z NextAuth v5, umożliwiające logowanie przy użyciu Touch ID, Face ID oraz systemowych kluczy sprzętowych bez konieczności wpisywania hasła. Klucze prywatne nigdy nie opuszczają urządzenia użytkownika, dzięki czemu phishing oraz wycieki baz haseł przestają stanowić realny wektor ataku.

Inteligentny Fallback UX

Jednym z problemów WebAuthn jest nieprzyjazne zachowanie przeglądarek wobec nowych użytkowników, którzy nie posiadają jeszcze zarejestrowanego Passkey.

Zamiast wyświetlać techniczne błędy API przeglądarki, aplikacja stosuje Inteligentny Fallback UX.

Jeżeli użytkownik nie posiada jeszcze biometrii:

  • aplikacja przechwytuje wyjątek WebAuthn,
  • wyświetla estetyczny modal zamiast błędu systemowego,
  • informuje o konieczności pierwszego logowania przez Google lub GitHub,
  • po zalogowaniu prowadzi użytkownika do ustawień profilu, gdzie może jednym kliknięciem aktywować Passkeys.

Dzięki temu onboarding pozostaje intuicyjny, a jednocześnie cała platforma może przejść na model passwordless-first.

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 .db w 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ń.

Architektura została rozszerzona o tabelę authenticator, przechowującą publiczne klucze WebAuthn. Relacja wykorzystuje kaskadowe usuwanie (ON DELETE CASCADE), dzięki czemu usunięcie konta automatycznie czyści również wszystkie zarejestrowane urządzenia biometryczne, bez pozostawiania osieroconych rekordów.

W celu minimalizacji liczby odczytywanych danych zastosowaliśmy również ultra-lekkie zapytanie server-side:

SELECT 1
FROM authenticator
WHERE userId = ?
LIMIT 1;

Dzięki pobieraniu wyłącznie informacji o istnieniu rekordu zamiast całego obiektu aplikacja znacząco ogranicza transfer danych, zużycie pamięci RAM oraz obciążenie bazy przy każdym renderze interfejsu.

3. Autoryzacja — NextAuth v5 (Dni 9–12)

Wybraliśmy NextAuth v5 (next-auth@5.0.0-beta) — 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
  • Passkeys (WebAuthn) — logowanie biometryczne przez Touch ID, Face ID i Windows Hello
  • Stable User ID — generujemy stabilne ID z account.providerAccountId, nie z token.sub; to kluczowe dla integralności danych między loginami
  • Middleware ochrony trasmiddleware.ts sprawdza 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, useOptimistic dla 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
  • date-fns
  • sonner
  • use-debounce
  • react-icons
  • next-themes
  • Vercel

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.

Dodatkowo logowanie biometryczne wykorzystuje standard FIDO2/WebAuthn, w którym prywatny klucz kryptograficzny pozostaje na urządzeniu użytkownika, a serwer przechowuje jedynie klucz publiczny wykorzystywany podczas procesu uwierzytelniania.

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  |
| Uwierzytelnianie                | WebAuthn + OAuth           | Passwordless      |
| Providerzy logowania            | Passkeys + Google + GitHub | —                 |
| Odpowiedź Edge Runtime          | <25 ms                     | <100 ms           |
| 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:

  1. Bezpieczeństwo by design — szyfrowanie, WebAuthn i autoryzacja nie są "do dodania później"; to fundament
  2. Zero backend overhead — Next.js Server Actions jako warstwy API; jeden deploy, jedna platforma
  3. Serverless-first — Turso + Vercel = zero kosztów operacyjnych dla małego i średniego ruchu
  4. Developer experience — TypeScript end-to-end, Zod validation, ESLint; kod gotowy na skalowanie
  5. Passwordless UX — biometryczne logowanie i inteligentny onboarding zapewniają bezpieczeństwo bez pogarszania doświadczenia użytkownika

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.