
Instrukcja - Tworzenie Treści
Przewodnik krok po kroku: od nowego obiektu w panelu Directusa, przez uprawnienia publiczne, po komponent na stronie. Spis istniejących kolekcji i ich pól jest w pliku directus/SCHEMA.md w repozytorium.
Słowniczek: kolekcja = tabela (np. Artykul), pole = kolumna, element = rekord, singleton = kolekcja z jednym elementem (np. Strona_Glowna).
1. Tworzenie kolekcji w panelu
Panel dev: http://localhost:8055 (lub http://cms.<slug>.localhost). Zaloguj się jako admin (dane w pliku .env).
- Settings (ikona koła zębatego w lewym pasku) → Data Model → przycisk + (Create Collection).
- Name: nazwa techniczna kolekcji. Zasady:
- po polsku, bez polskich znaków i spacji:
Artykul,Stopka_Linki,Partner; - liczba pojedyncza, pierwsza litera wielka, słowa łączone
_; - ta nazwa trafia do kodu frontendu, więc nie zmieniaj jej później.
- po polsku, bez polskich znaków i spacji:
- Primary Key: zostaw Generated UUID.
- Zakładka Optional System Fields: zaznacz
status(Published/Draft/Archived; frontend pokazuje tylko published),sort(ręczna kolejność),date_createdidate_updated(daty do sitemap). - Zapisz. Dla singletonu (np. ustawienia strony głównej) wejdź w kolekcję → ikona ołówka (Collection Setup) → włącz Singleton.
Dodawanie pól
W kolekcji kliknij Create Field i wybierz typ interfejsu. Najczęściej używane:
| Chcesz mieć | Wybierz w kreatorze | Nazwa techniczna (przykład) | Uwagi |
|---|---|---|---|
| krótki tekst | Input (String) | tytul, nazwa |
zaznacz Required dla tytułu |
| adres URL podstrony | Input (String) | slug |
zaznacz Unique; małe litery, myślniki |
| dłuższy tekst bez formatowania | Textarea | opis, krotki_opis |
do kart i meta description |
| treść z formatowaniem | WYSIWYG | tresc, artykul |
obrazki z edytora działają przez /assets/ |
| jeden obraz | Image | thumbnail, baner, emblemat |
w bazie zapisuje się id pliku |
| wiele plików do pobrania | Files (relacja M2M) | pliki |
Directus utworzy tabelę <Kolekcja>_files |
| data / data i godzina / godzina | Datetime z typem date / timestamp / time |
data_rozpoczecia, Data_publikacji, czas_rozpoczecia |
|
| wybór z listy | Dropdown | Typ, widocznosc, typ |
wpisz dozwolone wartości |
| tak / nie | Dropdown z wartościami tak/nie |
wymagane_zapisy |
w szablonie nie używamy Boolean (spójność z PNT) |
| liczba (kwota) | Input (Decimal) | wartosc_projektu |
|
| punkt na mapie | Map (Geometry, Point) | mapa |
wymaga PostGIS (jest w stacku) |
| link zewnętrzny | Input (String) | link, strona_wydarzenia |
pełny URL z https:// |
Wskazówki:
- Nazwa techniczna pola (Key) to to, co czyta frontend. Etykietę i opis ustawiasz dowolnie w zakładce Field.
- Nie da się zmienić Key po utworzeniu. Jeśli się pomylisz, usuń pole i utwórz ponownie.
- Pola z plikami (Image, Files) wymagają uprawnienia Public na
directus_files(w szablonie już jest).
Dodawanie treści
Content (ikona listy w lewym pasku) → kolekcja → +. Ustaw status na Published, inaczej frontend elementu nie pokaże. W polu slug wpisz np. jesienny-piknik.
2. Uprawnienia publiczne (bez tego frontend dostaje 403)
Frontend pobiera dane bez logowania, więc rola Public musi mieć odczyt każdej kolekcji, którą ma wyświetlać, oraz jej tabeli łączącej z plikami.
W panelu
- Settings → Access Policies → polityka Public.
- W sekcji Permissions kliknij Add Collection i wybierz kolekcję (np.
Partner). - W wierszu kolekcji kliknij ikonę w kolumnie Read (oko) → All Access.
- Jeśli kolekcja ma pole
pliki, powtórz dla tabeli<Kolekcja>_files(np.Partner_files). Tabele łączące są ukryte; w oknie Add Collection włącz System Collections lub wyszukaj po nazwie. directus_files→ Read jest już nadane. Nie nadawaj Public żadnych praw Create / Update / Delete.
Szybki test z terminala (oczekiwane 200):
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8055/items/Partner
Przez API (gdy wolisz skrypt)
# token admina
TOKEN=$(curl -s -X POST http://localhost:8055/auth/login -H 'Content-Type: application/json' \
-d '{"email":"<ADMIN_EMAIL>","password":"<ADMIN_PASSWORD>"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['data']['access_token'])")
# id polityki Public (nazwa wyświetla się jako "$t:public_label")
curl -s -H "Authorization: Bearer $TOKEN" 'http://localhost:8055/policies?fields=id,name'
# nadanie odczytu (podstaw PUBLIC_POLICY_ID)
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
http://localhost:8055/permissions -d '[
{"policy":"PUBLIC_POLICY_ID","collection":"Partner","action":"read","fields":["*"]},
{"policy":"PUBLIC_POLICY_ID","collection":"Partner_files","action":"read","fields":["*"]}
]'
Uprawnienia są zapisane w bazie, więc trafiają do seeda (seed/make-seed.sh) i do każdej nowej instalacji.
3. Przykład od początku do końca: kolekcja Partner → sekcja „Partnerzy” na stronie głównej
Krok A. Kolekcja w Directusie
- Data Model → + → Name:
Partner, pola systemowe:status,sort,date_created,date_updated. - Pola:
| Key | Interfejs | Ustawienia |
|---|---|---|
nazwa |
Input (String) | Required |
logo |
Image | |
link |
Input (String) | pełny URL |
opis |
Textarea | opcjonalny |
- Access Policies → Public → Add Collection
Partner→ Read: All Access. - Content → Partner → dodaj 3–4 elementy z logo, status Published.
- Test:
curl -s http://localhost:8055/items/Partnerzwraca JSON z elementami.
Krok B. Zgłoszenie dla programisty (lub asystenta AI)
Wystarczy komunikat w tej formie:
Utworzyłem w Directusie kolekcję
Partner(pola:nazwastring wymagane,logoimage,linkurl,opistextarea, systemowestatus/sort). Public ma odczyt. Chcę sekcję „Partnerzy” na stronie głównej pod projektami: siatka logotypów, kliknięcie otwieralinkw nowej karcie, sortowanie posort.
Z tego wynika wszystko, co trzeba zakodować. Jeśli kolekcja ma mieć podstrony (/cos/[slug]), dopisz to i dodaj pole slug.
Krok C. Frontend (co powstaje z takiego zgłoszenia)
1. Typ w frontend/src/lib/types.ts:
/** Kolekcja `Partner`. */
export interface Partner {
id: string;
status: Status;
sort?: number | null;
nazwa: string;
logo?: string | null; // id pliku
link?: string | null;
opis?: string | null;
}
2. Komponent frontend/src/components/PartnersSection.tsx (serwerowy, bez stanu):
import ScrollReveal from "./ScrollReveal";
import { assetUrl } from "@/lib/directus";
import type { Partner } from "@/lib/types";
export default function PartnersSection({ partners, title = "Partnerzy" }: { partners: Partner[]; title?: string }) {
if (partners.length === 0) return null;
return (
<section id="partnerzy" className="py-24 bg-gray-50 border-t border-gray-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<ScrollReveal>
<h2 className="text-3xl md:text-4xl font-bold text-primary text-center mb-16">{title}</h2>
</ScrollReveal>
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
{partners.map((p, idx) => (
<ScrollReveal key={p.id} delay={idx * 80}>
<a href={p.link || "#"} target="_blank" rel="noreferrer" title={p.opis || p.nazwa}
className="flex items-center justify-center bg-white rounded-2xl border border-gray-200 p-6 h-32 hover:shadow-lg hover:-translate-y-1 transition-all">
{p.logo ? (
// eslint-disable-next-line @next/next/no-img-element
<img src={assetUrl(p.logo, { width: 400, format: "webp" })} alt={p.nazwa} className="max-h-16 w-auto object-contain" />
) : (
<span className="font-bold text-primary text-center">{p.nazwa}</span>
)}
</a>
</ScrollReveal>
))}
</div>
</div>
</section>
);
}
3. Pobranie danych i wstawienie sekcji w frontend/src/app/page.tsx:
import PartnersSection from "@/components/PartnersSection";
import type { Partner } from "@/lib/types";
// ...
const partners = await getPublished<Partner>("Partner", { sort: "sort", fields: ["id", "nazwa", "logo", "link", "opis"] });
// ...w JSX, np. pod <ProjectsSection />:
<PartnersSection partners={partners} />
4. Dokumentacja: dopisz kolekcję do directus/SCHEMA.md. Jeśli ma podstrony, dodaj trasę w frontend/src/app/sitemap.ts.
5. Sprawdzenie: cd frontend && npm run lint && npx tsc --noEmit, potem npm run dev i podgląd strony głównej.
Krok D. Seed
Gdy kolekcje i treści przykładowe są gotowe: seed/make-seed.sh w katalogu głównym projektu i commit katalogu seed/. Nowe instalacje szablonu dostaną kolekcję, uprawnienia i dane od razu.
4. Lista kontrolna dla nowej kolekcji
- Nazwa kolekcji po polsku, bez znaków diakrytycznych, nie będzie zmieniana.
- Pola systemowe:
status,sort,date_created,date_updated. slug(Unique), jeśli kolekcja ma podstrony.- Public → Read na kolekcji i na
<Kolekcja>_files(jeśli jest polepliki). - Przynajmniej jeden element w statusie Published do testów.
curl http://localhost:8055/items/<Kolekcja>zwraca 200 z danymi.- Zgłoszenie dla programisty: nazwa, pola, gdzie i jak ma się wyświetlać.
- Po wdrożeniu na froncie: wpis w
SCHEMA.md, ewentualniesitemap.ts, odświeżony seed.
