Przejdź do treści

Jak wdrożyć bezpieczną autoryzację i middleware w Astro

Koniec z Lucią Auth. Zobacz jak skonfigurować nowoczesne sesje, bezpieczne middleware oraz logowanie przez OAuth w najnowszej wersji Astro.

Maciej Sala

Founder StriveLab

11 min czytaniaOpublikowano 29 maja 2026 (Aktualizacja 17 lipca 2026)

W poprzednim artykule o Astro Actions rzucaliśmy z akcji ActionError({ code: 'UNAUTHORIZED' }), gdy użytkownik nie był zalogowany. Ale skąd akcja wie, czy ktoś jest zalogowany? Odpowiedź to dwie współpracujące warstwy: middleware, które rozpoznaje użytkownika przy każdym żądaniu, i biblioteka uwierzytelniania, która zarządza sesją i logowaniem. Zaczniemy od middleware, bo to fundament.

Middleware w Astro — jeden punkt na trasie każdego żądania

to plik src/middleware.ts, który eksportuje funkcję onRequest. Astro wykrywa go automatycznie, nie ma osobnego włączania w konfiguracji. Funkcja dostaje dwa argumenty: context (z danymi żądania) i next (kontynuacja przetwarzania):

Code
// src/middleware.ts
import { defineMiddleware } from 'astro:middleware'
 
export const onRequest = defineMiddleware(async (context, next) => {
  // Kod tutaj wykonuje się PRZED renderem strony
  console.log('Żądanie do:', context.url.pathname)
 
  // Przepuść żądanie dalej i zwróć odpowiedź
  return next()
})

Funkcja pomocnicza daje pełne typowanie context i next, bo bez niej musiałbyś typować argumenty ręcznie.

Każde renderowanie przechodzi przez ten jeden punkt: podczas procesu budowania tras prerenderowanych albo przy żądaniu do tras renderowanych na żądanie. To czyni middleware dobrym miejscem na bramkę autoryzacji w części serwerowej, czyli sprawdzasz raz, centralnie, zamiast powtarzać warunek na każdej chronionej stronie.

context.locals — przeniesienie użytkownika do stron

Sprawdzenie sesji w middleware jest bezużyteczne, jeśli wynik nie dotrze do strony. Od tego jest — obiekt, który żyje przez cały cykl pojedynczego żądania:

Code
// src/middleware.ts
import { defineMiddleware } from 'astro:middleware'
import { auth } from '@/lib/auth' // konfiguracja Better Auth
 
export const onRequest = defineMiddleware(async (context, next) => {
  const session = await auth.api.getSession({
    headers: context.request.headers,
  })
 
  // Zapisujemy użytkownika i sesję do locals — dostępne na każdej stronie
  context.locals.user = session?.user ?? null
  context.locals.session = session?.session ?? null
 
  return next()
})

Żeby TypeScript wiedział, co siedzi w locals, deklarujesz typ raz w env.d.ts, czyli mamy tu tą samą filozofię typowania u źródła, co przy w przypadku typowanych Content Collections z Zod:

Code
// src/env.d.ts
declare namespace App {
  interface Locals {
    user: import('better-auth').User | null
    session: import('better-auth').Session | null
  }
}

Teraz na dowolnej stronie .astro masz otypowany dostęp:

Code
---
const { user } = Astro.locals
 
if (!user) {
  return Astro.redirect('/login')
}
---
 
<p>Witaj, {user.name}</p>

To samo Astro.locals.user jest dostępne w Astro Actions przez context.locals i właśnie stąd akcja wie, czy rzucić UNAUTHORIZED.

Uwierzytelnianie to nie autoryzacja

Sesja pozwala zidentyfikować użytkownika (czyli kto wysłał żądanie), ale nie rozstrzyga o jego uprawnieniach do konkretnej operacji. O ile przekierowanie niezalogowanej osoby z /panel jest jedynie procesem uwierzytelniania, o tyle weryfikacja roli, członkostwa w organizacji czy prawa własności do rekordu stanowi autoryzację i musi być każdorazowo przeprowadzana na poziomie dostępu do danych.

Dlatego middleware jest dobrą bramką dla całych sekcji, ale nie zastępuje kontroli uprawnień w Astro Actions i endpointach. Obsługa żądania zmieniającego fakturę powinna pobrać użytkownika z context.locals, a następnie ograniczyć zapytanie także identyfikatorem właściciela lub organizacji. Samo ukrycie strony nie chroni bezpośredniego wywołania operacji.

Ochrona ścieżek w Astro — bramka autoryzacji w jednym miejscu

Mając użytkownika w locals, bramkę dla całych sekcji stawiasz w middleware, nie na każdej stronie z osobna:

Code
// src/middleware.ts
import { defineMiddleware } from 'astro:middleware'
import { auth } from '@/lib/auth'
 
const PROTECTED = ['/panel', '/profil', '/ustawienia', '/api/notatki']
 
// "/panel" ma chronić też "/panel/faktury", ale nie "/panel-pomocy"
const isProtected = (path: string) =>
  PROTECTED.some((p) => path === p || path.startsWith(p + '/'))
 
export const onRequest = defineMiddleware(async (context, next) => {
  const path = context.url.pathname
 
  // Endpointy Better Auth muszą pozostać dostępne — inaczej
  // zablokujesz logowanie i callbacki OAuth
  if (path === '/api/auth' || path.startsWith('/api/auth/')) {
    return next()
  }
 
  const session = await auth.api.getSession({
    headers: context.request.headers,
  })
  context.locals.user = session?.user ?? null
  context.locals.session = session?.session ?? null
 
  if (isProtected(path) && !context.locals.user) {
    // Klient API oczekuje statusu, nie strony logowania
    if (path.startsWith('/api/')) {
      return new Response(JSON.stringify({ error: 'Unauthorized' }), {
        status: 401,
        headers: { 'Content-Type': 'application/json' },
      })
    }
 
    // Nawigacja przeglądarki: przekierowanie z zachowaniem celu
    return context.redirect(`/login?from=${encodeURIComponent(path)}`)
  }
 
  return next()
})

Jedna lista, jedno sprawdzenie, jedna decyzja — dodanie nowej chronionej ścieżki to dopisanie wpisu do tablicy, a nie pamiętanie o warunku na każdej nowej stronie.

Trzy detale w tym kodzie są nieprzypadkowe. Dopasowanie path === p || path.startsWith(p + '/') chroni /panel i wszystko poniżej, ale nie łapie przypadkiem /panel-pomocy, które gołe startsWith('/panel') też by objęło. Wyłączenie /api/auth zapobiega scenariuszowi, w którym bramka blokuje sam mechanizm logowania — callback OAuth nigdy nie ma sesji, bo dopiero ją tworzy. A rozdzielenie odpowiedzi dla API i stron bierze się stąd, że middleware w Astro obsługuje także endpointy: fetch z klienta, który zamiast JSON-a z 401 dostanie przekierowanie i HTML strony logowania ze statusem 200, to klasyczne źródło trudnych do debugowania błędów parsowania.

sequence() — łańcuch middleware zamiast monolitu

Realna aplikacja potrzebuje więcej niż uwierzytelniania: logowanie żądań, i18n, nagłówki bezpieczeństwa. Wrzucanie wszystkiego do jednego onRequest szybko robi się nieczytelne. rozdziela odpowiedzialności:

Code
// src/middleware.ts
import { sequence } from 'astro:middleware'
import { logging } from './middleware/logging'
import { authGuard } from './middleware/auth'
import { securityHeaders } from './middleware/headers'
 
export const onRequest = sequence(logging, authGuard, securityHeaders)

Middleware wykonują się w kolejności na żądaniu, a odpowiedzi wracają w odwrotnej — jak warstwy cebuli. Każda funkcja robi jedną rzecz i da się ją testować w izolacji.

Uwierzytelnianie w 2026: Better Auth zamiast biblioteki Lucia v3

Od razu zaznaczam, że Lucia v3, która przez lata była popularnym rozwiązaniem uwierzytelniania dla Astro, została zdeprecjonowana jako biblioteka w marcu 2025 roku. W związku z tym adaptery przestały być rozwijane już pod koniec 2024 roku, a jej twórca świadomie przekształcił Lucię w przewodnik architektoniczny. Jest on nadal cenny jako nauka wzorców (sesje, tokeny, OAuth), ale pakietu lucia nie instalujesz jako aktywnie utrzymywanej zależności w nowym projekcie.

Astro nie ma jednej oficjalnej biblioteki uwierzytelniania. W 2026 roku jednym z głównych wyborów z bezpośrednim wsparciem Astro jest :

  • TypeScript-first — pełne typowanie sesji i użytkownika, bez ręcznego deklarowania.
  • Oficjalne wtyczki 2FA, passkeys i organizacji — funkcje, które w prostszych bibliotekach dokładasz samodzielnie.
  • System wtyczek i aktywny rozwój.

Alternatywami są m.in. Clerk, Supabase Auth, Firebase Authentication lub własna implementacja sesji oparta na aktualnym przewodniku Lucii. Wybór zależy od tego, czy chcesz utrzymywać dane i przepływy uwierzytelniania samodzielnie, czy korzystać z zarządzanej usługi. W tym przykładzie używamy Better Auth, bo ma bezpośredni przewodnik integracji z Astro i działa na standardowych obiektach Request/Response.

Konfiguracja Better Auth — od zera do działającej sesji

Teraz przejdźmy do kompletnej konfiguracji. Better Auth ma jedno źródło prawdy, a jest nim plik lib/auth.ts, w którym łączysz bibliotekę z bazą i włączasz metody logowania. W tym przykładzie używamy bazy libSQL (lokalny SQLite podczas programowania, Turso na produkcji) obsługiwanej przez , więc potrzebujesz Better Auth, adaptera Drizzle i samego ORM:

Code
npm install better-auth @better-auth/drizzle-adapter drizzle-orm
npm install -D drizzle-kit

Następnie konfigurujesz drizzleAdapter z providerem sqlite:

Code
// src/lib/auth.ts
import { betterAuth } from 'better-auth'
import { drizzleAdapter } from '@better-auth/drizzle-adapter'
import { db } from '@/db' // Twoja instancja Drizzle
 
export const auth = betterAuth({
  database: drizzleAdapter(db, { provider: 'sqlite' }),
  emailAndPassword: { enabled: true },
  socialProviders: {
    github: {
      clientId: import.meta.env.GITHUB_CLIENT_ID,
      clientSecret: import.meta.env.GITHUB_CLIENT_SECRET,
    },
  },
  session: {
    expiresIn: 60 * 60 * 24 * 7, // sesja żyje 7 dni
    updateAge: 60 * 60 * 24, // co dobę odświeża termin ważności
  },
})

Metodę auth.api.getSession, z której korzystałeś już w middleware, wywołujesz z tej samej instancji. Better Auth pobiera secret oraz baseURL bezpośrednio ze zmiennych BETTER_AUTH_SECRET i BETTER_AUTH_URL w pliku .env. Pamiętaj, że sekret powinien mieć co najmniej 32 znaki i wysoką entropię, a na produkcji zawsze definiuj baseURL jawnie, ponieważ odpowiada on m.in. za poprawne działanie callbacków OAuth.

Pamięć podręczna sesji w ciasteczku — bez zapytania do bazy przy każdym żądaniu

Zanim pójdziemy dalej, jedna rzecz, którą widać dopiero pod obciążeniem. Skoro middleware wywołuje getSession przy każdym żądaniu renderowanym na żądanie, to każde wejście na dowolną stronę oznacza zapytanie do bazy i to także na stronach publicznych, gdzie użytkownika sprawdzasz tylko po to, żeby pokazać „Zaloguj" albo avatar. Przy libSQL na tym samym serwerze to pomijalne, ale przy bazie dostępnej przez sieć (Turso, Postgres u innego dostawcy) dokładasz dodatkowe zapytanie sieciowe do każdego żądania.

Better Auth rozwiązuje to wbudowaną pamięcią podręczną sesji w ciasteczku (cookieCache): podpisane dane sesji lądują w krótkotrwałym ciasteczku i przez skonfigurowany czas getSession czyta je stamtąd, nie dotykając bazy:

Code
// src/lib/auth.ts — fragment konfiguracji
session: {
  expiresIn: 60 * 60 * 24 * 7,
  updateAge: 60 * 60 * 24,
  cookieCache: {
    enabled: true,
    maxAge: 60 * 5, // przez 5 minut sesja jest czytana z ciasteczka
  },
},

Przyjmij świadomy kompromis, w którym przez czas określony w maxAge sesja, która powinna być już nieważna (np. po wylogowaniu na innym urządzeniu lub zablokowaniu konta), może być nadal traktowana jako aktywna. Z tego powodu ustawiaj maxAge na krótki okres (liczony w minutach), a przy operacjach krytycznych, takich jak zmiana hasła czy realizacja płatności, zawsze wymuszaj weryfikację poprzez bezpośrednie odpytanie bazy danych.

Wymuszenie świeżego odczytu nie polega na drugim zwykłym wywołaniu getSession, bo ono nadal może użyć pamięci podręcznej ciasteczka. Przekaż jawnie disableCookieCache: true:

Code
const freshSession = await auth.api.getSession({
  headers: context.request.headers,
  query: { disableCookieCache: true },
})

Domyślna strategia compact podpisuje dane z pamięci podręcznej, ale ich nie szyfruje. Klient nie może ich zmienić bez unieważnienia podpisu, może je jednak odczytać. Nie dodawaj więc do obiektu sesji sekretów. W sytuacji kiedy jest wymagana poufność zawartości ciasteczka, Better Auth udostępnia strategię jwe, co też oznacza jego większy rozmiar.

Trasa catch-all i migracje

Better Auth nie wpina się do tras automatycznie, ponieważ potrzebuje jednej trasy catch-all, która obsłuży logowanie, adresy zwrotne OAuth i wylogowanie pod /api/auth/*:

Code
// src/pages/api/auth/[...all].ts
import { auth } from '@/lib/auth'
import type { APIRoute } from 'astro'
 
export const prerender = false // zbędne przy output: 'server'
 
export const ALL: APIRoute = (ctx) => auth.handler(ctx.request)

Jeśli cały projekt ma output: 'server', eksport prerender = false jest zbędny. Przy domyślnym output: 'static' pozostaw go w pliku i skonfiguruj adapter, żeby Astro nie próbowało wygenerować endpointu podczas buildu.

Narzędzie wiersza poleceń Better Auth generuje schemat Drizzle wymagany przez aktualną konfigurację i wtyczki. Samo wygenerowanie pliku nie zmienia jednak bazy, bo migrację tworzysz i wykonujesz narzędziami Drizzle:

Code
npx auth@latest generate
npx drizzle-kit generate
npx drizzle-kit migrate

Powtórz ten proces po zmianie konfiguracji uwierzytelniania, która dodaje pola lub tabele, np. po włączeniu wtyczki organizacji albo 2FA. W repozytorium zachowaj zarówno wygenerowany schemat, jak i pliki migracji.

OAuth i sesje — pełny obieg logowania

Mając konfigurację i endpoint, logowanie społecznościowe to jedno wywołanie po stronie klienta. Better Auth ma osobny klient (auth-client.ts), którego używasz w komponentach interaktywnych, np. na przycisku „Zaloguj przez GitHub":

W panelu dostawcy OAuth musisz wcześniej zarejestrować dokładny adres zwrotny Better Auth, np. https://example.com/api/auth/callback/github. callbackURL: '/panel' z kodu poniżej oznacza stronę docelową po zakończeniu logowania, a nie adres zwrotny rejestrowany u GitHuba. To dwa różne adresy.

Code
// src/lib/auth-client.ts
import { createAuthClient } from 'better-auth/client'
 
export const authClient = createAuthClient()
Code
// w komponencie po stronie klienta
import { authClient } from '@/lib/auth-client'
 
await authClient.signIn.social({
  provider: 'github',
  callbackURL: '/panel', // dokąd wrócić po udanym logowaniu
})

Reszta dzieje się sama. Pełny obieg wygląda tak — i to właśnie middleware spina go ze stronami:

  1. Logowanie. signIn.social przekierowuje do GitHuba i po zgodzie użytkownika dostawca wraca na /api/auth/callback/github, którą obsługuje trasa catch-all. Better Auth tworzy sesję, zapisuje ją w bazie i ustawia ciasteczko.
  2. Każde kolejne żądanie. Middleware czyta ciasteczko, woła getSession, wstawia użytkownika do context.locals. Twoja bramka ze ścieżek już go widzi.
  3. Strony i akcje czytają Astro.locals.user, nie znając przy tym szczegółów sesji ani tego, czy zalogowanie poszło hasłem, czy poprzez OAuth.
Diagram
Obieg logowania OAuth i rola middleware: trasa catch-all tworzy sesję raz, middleware rozpoznaje ją przy każdym kolejnym żądaniu.

Wylogowanie jest symetryczne — signOut kasuje sesję w bazie i czyści ciasteczko, więc przy następnym żądaniu middleware ustawi user na null:

Code
import { authClient } from '@/lib/auth-client'
 
await authClient.signOut({
  fetchOptions: { onSuccess: () => (window.location.href = '/') },
})

Bezpieczeństwo — czego pilnować

  • Nie twórz własnego mechanizmu uwierzytelniania. Sesje, hashowanie haseł i OAuth to obszary, gdzie bardzo łatwo o luki. Jeśli nie posiadasz odpowiedniego doświadczenia w projektowaniu takich mechanizmów, użyj sprawdzonej biblioteki lub zarządzanej usługi.

  • Middleware to nie jedyna bramka. Astro Actions i endpointy też sprawdzają uprawnienia. Middleware chroni nawigację, ale mutacje danych weryfikuj dodatkowo w handlerze. Gdy obok zalogowania dochodzą role i uprawnienia, sięgnij po wzorce z artykułu o RBAC w Next.js — różnica frameworka jest kosmetyczna, model autoryzacji ten sam.

  • Ciasteczka sesji: HttpOnly, Secure, SameSite. Dobra biblioteka ustawia je domyślnie. Zweryfikuj, że tak jest, zwłaszcza na produkcji po HTTPS.

  • Ogranicz pochodzenie żądań przeciw . Better Auth domyślnie blokuje żądania spoza znanych domen, dlatego na produkcji musisz jawnie wskazać zaufane adresy w tablicy trustedOrigins. Nie wpisuj tam ścieżek adresu zwrotnego OAuth, bo dokładny adres zwrotny konfigurujesz w panelu dostawcy. Nie wyłączaj disableCSRFCheck ani disableOriginCheck w produkcji.

  • Waliduj przekierowanie po zalogowaniu. Parametr ?from= z URL-a może zostać podmieniony na adres zewnętrzny — dopuszczaj tylko ścieżki względne w obrębie swojej domeny, np. warunkiem from.startsWith('/') && !from.startsWith('//').

  • Ogranicz tempo prób logowania. Endpointy /api/auth/* to naturalny cel ataków brute force i credential stuffingu. Better Auth ma wbudowany (domyślnie włączony na produkcji, zaostrzony dla tras logowania) — zweryfikuj jego konfigurację, a przy deploymentach za proxy upewnij się, że biblioteka widzi prawdziwe IP klienta, nie adres load balancera. Ufaj tylko nagłówkowi nadpisywanemu przez własne proxy, np. CF-Connecting-IP; nagłówek przesłany bezpośrednio przez klienta można sfałszować.

  • Dobierz trwały magazyn rate limitera. Better Auth domyślnie przechowuje liczniki w pamięci procesu. Na serverless i przy wielu instancjach taki limit nie jest globalny i zeruje się wraz z instancją — użyj bazy albo secondaryStorage, jeśli limiter ma skutecznie obejmować cały deployment.

Ultraszybkie projekty, łączące lekkość ze skalowalnością.
Astro

Często zadawane pytania

Gdzie żyje middleware w Astro i jak je włączyć?

W pliku src/middleware.ts (albo src/middleware/index.ts), który eksportuje funkcję onRequest. Nie ma osobnego włączania w konfiguracji, bo Astro wykrywa plik automatycznie. Funkcja pomocnicza defineMiddleware daje pełne typowanie context i next.

Czy middleware w Astro wymaga trybu serwerowego?

Tak, dla realnej autoryzacji. Middleware uruchamia się też przy buildzie dla stron prerenderowanych, ale dostęp do ciasteczek, nagłówków oraz przekierowania i sprawdzanie sesji wymagają renderowania na żądanie: output: server albo trasy z prerender = false i adapter SSR.

Której biblioteki auth użyć w Astro w 2026?

Astro nie narzuca oficjalnego rozwiązania uwierzytelniania. Better Auth jest jednym z głównych wyborów dla nowych projektów: działa bezpośrednio z Astro, jest TypeScript-first, a 2FA, passkeys i organizacje udostępnia przez oficjalne wtyczki. Lucia v3 została zdeprecjonowana jako biblioteka w marcu 2025 i jest dziś przewodnikiem architektonicznym, nie zależnością do instalowania.

Jak przekazać zalogowanego użytkownika z middleware do stron?

Przez context.locals — obiekt, który żyje przez cały cykl jednego żądania. W middleware ustawiasz context.locals.user i context.locals.session po weryfikacji sesji, a na stronach .astro czytasz Astro.locals. Typy deklarujesz raz w env.d.ts przez interfejs App.Locals.

Jak łączyć kilka middleware w Astro?

Funkcją sequence z astro:middleware. Łączysz funkcje w kolejności wykonania, np. sequence(logging, auth, i18n) — na żądaniu wykonują się po kolei, a odpowiedzi wracają w odwrotnej kolejności. Dzięki temu rozdzielasz odpowiedzialności zamiast pisać jedno gigantyczne onRequest.

Jak dodać logowanie przez OAuth (GitHub, Google) w Better Auth?

W pliku src/lib/auth.ts dodajesz wpis do socialProviders z clientId i clientSecret dostawcy, a w aplikacji potrzebujesz catch-all route src/pages/api/auth/[...all].ts eksportującego auth.handler. Na froncie wołasz authClient.signIn.social({ provider: "github", callbackURL: "/panel" }) — Better Auth przekierowuje do dostawcy, obsługuje callback, tworzy sesję i ustawia ciasteczko. Wymaga renderowania on-demand (output: server lub prerender = false na trasie auth).

Jak długo żyje sesja w Better Auth i jak to ustawić?

W konfiguracji betterAuth() w bloku session: expiresIn to całkowity czas życia sesji w sekundach (domyślnie 7 dni), a updateAge określa, jak często termin ważności jest odświeżany przy aktywności (domyślnie co dobę). Sesję kasujesz przez authClient.signOut, co usuwa ją z bazy i czyści ciasteczko — przy następnym żądaniu middleware ustawi Astro.locals.user na null.

Czy middleware powinno przekierowywać także żądania do API?

Nie. Przekierowanie na /login ma sens dla nawigacji przeglądarki, ale klient wywołujący endpoint API oczekuje statusu, a nie strony logowania. W bramce rozdziel te przypadki: dla ścieżek zaczynających się od /api zwróć Response ze statusem 401 i JSON-em, a dla stron będzie context.redirect. Pamiętaj też, żeby wyłączyć z bramki /api/auth, bo inaczej zablokujesz sam mechanizm logowania.

Czy getSession w middleware nie obciąża bazy przy każdym żądaniu?

Domyślnie każde żądanie do strony on-demand oznacza zapytanie o sesję do bazy. Better Auth ma na to cookieCache, który podpisuje dane sesji w ciasteczku, ważne przez konfigurowalny maxAge (np. 5 minut). W tym oknie getSession czyta dane z ciasteczka bez dotykania bazy, a po wygaśnięciu weryfikuje sesję ponownie. To dobry kompromis między wydajnością a możliwością szybkiego unieważnienia sesji.

Jak zabezpieczyć Better Auth przed CSRF na produkcji?

Better Auth domyślnie sprawdza nagłówek Origin i odrzuca żądania spoza znanych adresów. Na produkcji jawnie ustaw trustedOrigins w konfiguracji betterAuth() listę dodatkowych originów aplikacji, którym ufasz. Callback OAuth rejestrujesz osobno w panelu dostawcy. Nie wyłączaj walidacji originu ani CSRF; sprawdź też, czy produkcyjne ciasteczka zachowują bezpieczne ustawienia HttpOnly, Secure i SameSite.

O autorze

Maciej Sala

Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwijam własne projekty.

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną

Biblioteka wiedzy na temat Astro

Czytaj dalej

Zobacz więcej wpisów
Middleware w Next.js — 7 zastosowań i typowych pułapek

Większość deweloperów może kojarzyć middleware w Next.js ze sprawdzaniem, czy użytkownik jest zalogowany, podczas gdy dla żądań objętych matcherem może ono podjąć decyzję jeszcze przed routingiem: przypisać wariant eksperymentu, zastosować limit, wykonać rewrite albo dodać zależny od requestu nagłówek. W artykule chciałem omówić siedem optymalnych i bezpiecznych zastosowań Proxy.

Maciej Sala

Maciej Sala

Founder StriveLab

Jak bezpiecznie obsługiwać formularze w Astro?

Klasyczny formularz bardzo szybko robi się ciężki przez takie elementy jak endpoint, odczytywanie ciała żądania, walidacja, statusy HTTP, fetch po stronie klienta i typy przepisane drugi raz. Na ratunek przybywają Astro Actions: wystarczy, że zdefiniujesz logikę funkcji serwerowej, dodasz schemat Zod i wywołasz ją z klienta bez ręcznego składania REST API.

Maciej Sala

Maciej Sala

Founder StriveLab

Astro vs Next.js w 2026: Porównanie frameworków

Astro czy Next.js? Wybór frameworka musi być dokładnie przemyślany, zanim pojawi się pierwszy commit. Jeśli stoisz przed takim właśnie wyborem, w tym artykule staram się wykazać, w jakich obszarach najlepiej sprawdza się Astro , a w jakich będzie dominował Next.js .

Maciej Sala

Maciej Sala

Founder StriveLab