Pomiń do treści
Netova
← Wszystkie realizacje

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

Plan Biznes🔗 Zobacz stronę na żywo
Next.jsTursoNextAuthPWAAES-256Framer MotionPerformance

95+/100

Performance

100/100

SEO Score

100/100

Accessibility

AES-256

security

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
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 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=strict cookies 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 .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ń.

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 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; 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
  • revalidatePath po każdej mutacji — ISR-style cache invalidation; UI zawsze aktualny
  • unstable_noStore — wyłączenie cache dla odczytu zadań; każde wczytanie pobiera świeże dane
  • useCallback na refreshTodos — 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:

  1. Bezpieczeństwo by design — szyfrowanie 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

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.