DOKUMENTACJA · WERSJA 1.0 · AKTUALIZACJA PO KAŻDEJ ZMIANIE FUNKCJI
Wszystko, co potrzebne, żeby prowadzić tę stronę bez znajomości HTML-a i bez rozmowy z autorem: dodawanie treści, podmiana grafiki, publikacja, kopie zapasowe i wdrożenie na serwer.
Szopa na Wsi to strona warsztatu technologicznego z własnym systemem zarządzania treścią. Nie korzysta z WordPressa ani żadnej usługi zewnętrznej — cała treść, zdjęcia i baza danych leżą na Waszym serwerze.
DLA ODWIEDZAJĄCYCH
Strona główna, projekty, artykuły, o nas, wyszukiwarka. Wszystko generowane z bazy danych.
/ADMIN · LOGOWANIE
Dodawanie i edycja treści, biblioteka zdjęć, ustawienia. Tylko dla Was.
JEDEN PLIK SQLITE
Wszystkie artykuły, projekty i opisy zdjęć w jednym pliku obok programu.
KATALOG UPLOADS/
Wgrane zdjęcia w oryginale plus automatycznie utworzone wersje w mniejszych rozmiarach.
| Adres | Co pokazuje | Skąd bierze treść |
|---|---|---|
/ | Strona główna | wyróżnione projekty + 3 najnowsze artykuły + ustawienia |
/projekty | Wszystkie projekty z filtrem tagów | projekty ze statusem „Opublikowany” |
/projekty/nazwa | Strona projektu | pojedynczy projekt |
/artykuly | Magazyn z podziałem na serie | artykuły opublikowane |
/artykuly/nazwa | Artykuł | pojedynczy artykuł |
/o-nas | Manifest i wyposażenie | kod strony + ustawienia |
/szukaj | Wyszukiwarka | tytuły, opisy, treść, tagi, kody |
/admin | Panel | — |
Na komputerze, na którym strona ma działać, potrzebny jest Node.js w wersji 20 lub nowszej.
npm install # instalacja zależności (raz)
cp .env.example .env # konfiguracja
npm run setup # baza danych + treści startowe
npm run dev # uruchomienie w trybie roboczym
Strona działa pod adresem http://localhost:3000, panel pod http://localhost:3000/admin.
| Ustawienie | Do czego służy |
|---|---|
DATABASE_URL | Ścieżka do pliku bazy. Domyślnie file:./dev.db — nie trzeba zmieniać. |
AUTH_SECRET | Musi być zmienione. Losowy ciąg min. 32 znaki — podpisuje sesję logowania. |
ADMIN_EMAIL, ADMIN_PASSWORD | Pierwsze konto administratora. Używane tylko przy npm run setup. |
NEXT_PUBLIC_SITE_URL | Pełny adres strony. Wpływa na linki w Google i podglądy w mediach społecznościowych. |
AUTH_SECRET na losowy ciąg, zmieńcie hasło administratora w panelu
i ustawcie NEXT_PUBLIC_SITE_URL na docelowy adres. Wygenerowanie sekretu:
openssl rand -base64 48
Wejdźcie na /admin. Jeśli nie jesteście zalogowani, strona przekieruje na formularz logowania.
Sesja trwa 7 dni.
| Zakładka | Do czego |
|---|---|
| Dashboard | Liczby, ostatnie zmiany, szybkie akcje, przypomnienie jak dodać wpis |
| Artykuły | Lista wszystkich wpisów, dodawanie, edycja, usuwanie |
| Projekty | To samo dla projektów |
| Media | Wszystkie zdjęcia: wgrywanie, opisy, usuwanie |
| Ustawienia | Nazwa strony, hasło w hero, kontakt, zmiana hasła |
Ustawienia → Zmiana hasła. Podajecie obecne i nowe (min. 10 znaków). Zróbcie to zaraz po pierwszym zalogowaniu.
/artykuly/jak-dobrac-frez. Można go nadpisać ręcznie.| Status | Znaczenie |
|---|---|
| Szkic | Widoczny tylko w panelu. Domyślny dla nowego wpisu. |
| Opublikowany | Widoczny na stronie, w wyszukiwarce i mapie witryny. |
| Archiwum | Zdjęty ze strony, ale zachowany w panelu. |
Przycisk Publikuj przełącza między szkicem a publikacją. Wpis już opublikowany ma przycisk Cofnij do szkicu.
Piszecie jak w edytorze tekstu — nie trzeba znać HTML-a. Pasek narzędzi nad polem:
| Przycisk | Co robi |
|---|---|
| B / I / S | Pogrubienie, kursywa, przekreślenie |
| H2 / H3 | Nagłówek sekcji i podsekcji. H1 to tytuł wpisu — nie używajcie go w treści. |
| ¶ | Zwykły akapit (cofa nagłówek) |
| • Lista / 1. Lista | Wypunktowanie i lista numerowana |
| ❝ | Cytat — wyróżniony większą czcionką z bursztynową kreską |
| ‹/› / KOD | Kod w linii tekstu / blok kodu |
| — | Linia oddzielająca |
| LINK | Wstawia odnośnik. Puste pole usuwa istniejący link. |
| ZDJĘCIE | Otwiera bibliotekę — wybór lub wgranie nowego |
| GALERIA | Kilka zdjęć obok siebie w siatce (zaznaczcie wiele) |
| YOUTUBE | Wklejcie adres filmu — osadzi się w treści |
| TABELA | Wstawia tabelę 3×3; po kliknięciu w nią pojawiają się przyciski dodawania kolumn i wierszy |
| ↶ / ↷ | Cofnij / ponów |
W treściach przygotowanych wcześniej znajdziecie ramki z napisem MIEJSCE NA ZDJĘCIE i opisem, co ma się w nich znaleźć. Żeby je zastąpić: ustawcie kursor w ramce, skasujcie ją klawiszem Backspace, po czym wstawcie zdjęcie przyciskiem ZDJĘCIE.
Projekt ma więcej pól niż artykuł, bo opisuje realizację od problemu do wniosków.
CNC-017. Konwencja: skrót dziedziny plus numer.| Sekcja | Co tu wpisać |
|---|---|
| PROBLEM | Co było nie tak. Bez tego reszta nie ma sensu. |
| POMYSŁ | Jak zamierzaliście to rozwiązać i dlaczego tak. |
| PROJEKT | Model, schemat, architektura, parametry. |
| REALIZACJA | Jak przebiegło wykonanie, co zaskoczyło. |
| EFEKT | Wynik z liczbami. |
| WNIOSKI | Co zrobilibyście inaczej. Ta sekcja ma osobną, wyróżnioną ramkę. |
Pary etykieta–wartość wyświetlane w pasku pod tytułem: TOOL → 6 mm END MILL,
MATERIAL → SKLEJKA 18. Dodajcie tyle, ile ma sens — cztery wyglądają najlepiej.
Pola PROJECT, STATUS i DATA dopisują się same.
Wyróżniony — projekt trafia na stronę główną. Kolejność — mniejsza liczba znaczy wyżej na liście.
Są trzy sytuacje. Wszystkie robi się w przeglądarce, bez kopiowania plików na serwer.
Kliknijcie zdjęcie w edytorze i skasujcie Backspace, potem wstawcie nowe przyciskiem ZDJĘCIE.
Sekcja Wall of experiments pobiera sześć najnowszych zdjęć z biblioteki. Żeby ją zmienić, wgrajcie nowe pliki w Media — pojawią się tam automatycznie. Sloty bez zdjęcia pokazują techniczny rysunek z opisem, czego brakuje.
| Parametr | Zalecenie |
|---|---|
| Format | JPG lub PNG (PNG gdy potrzebna przezroczystość) |
| Szerokość | 2000–3000 px. Mniejsze będą rozmyte na dużych ekranach. |
| Waga | Do 20 MB. Program i tak zrobi lżejsze wersje. |
| Proporcje | Poziome (16:9 lub 3:2) — tak wyglądają kafle i nagłówki |
Panel → Media. Tu leżą wszystkie zdjęcia.
Artykuł i projekt mogą mieć animowany schemat. Wybiera się go z listy — pole DIAGRAM PROCESU w prawej kolumnie edytora. Nie trzeba nic rysować.
| Grupa | Co pokazuje |
|---|---|
| Procesy warsztatowe | drewno, CNC, AI, fotografia produktowa, ogólny przepływ |
| Architektury (serie) | 15 schematów z artykułów: agent, RAG, segmentacja, bazowanie wizyjne i inne |
| Projekty | po jednym na każdy program, część z animacją lub odtwarzaczem |
Diagram pojawia się pod leadem artykułu albo po opisie projektu. Żeby go usunąć, wybierzcie pozycję brak.
Schematy blokowe opisuje się danymi, nie rysuje. Jeden wpis w
src/components/diagrams/specs.tsx to jeden diagram:
'moj-diagram': {
title: 'MOJ.FLOW',
accent: 'var(--color-ai)',
steps: [
{ label: 'WEJŚCIE', kind: 'input' },
{ label: 'DECYZJA', kind: 'decide' },
{ label: 'WYNIK', kind: 'output' },
],
loops: [{ from: 3, to: 2, label: 'POPRAWKA' }],
}
Typ kroku (input, decide, tool, process,
control, store, output) decyduje o kształcie i kolorze węzła.
Układ i połączenia liczą się same. Dostępne są dwa układy: serpentine (domyślny)
i ring dla procesów cyklicznych.
Seria grupuje wpisy w cykl czytany po kolei. Pole SERIA w edytorze artykułu.
| Seria | Tematyka |
|---|---|
| LOCAL AI LAB | Agenci, narzędzia, dane i wyszukiwanie uruchamiane lokalnie |
| VISION LAB | Segmentacja, maski, obróbka wsadowa, kontrola jakości zdjęć |
| CNC LAB | CAM, parametry skrawania, bazowanie, nasłuch maszyny |
| CONNECTED WORKSHOP | Spinanie zdjęć, modeli, danych i maszyn w jeden system |
Serie wyświetlają się jako cztery kafle na górze /artykuly; kliknięcie filtruje listę.
Na stronie artykułu seria jest plakietką nad tytułem.
Nową serię dodaje programista w pliku src/lib/taxonomy.ts — tablica SERIES
i opis w SERIES_META.
Strony takie jak /o-nas są częścią kodu, nie bazy danych — dzięki temu mogą mieć
własny układ. Dodanie nowej wymaga programisty, ale jest proste.
src/app/(site)/nazwa/page.tsx.o-nas/page.tsx jako punkt wyjścia.src/components/site/Header.tsx, tablica NAV.src/app/sitemap.ts.Katalog (site) w nazwie jest celowy: wszystko w nim dostaje nagłówek, stopkę i efekty
części publicznej. Panel administracyjny leży poza nim i ma własną, surową ramę.
const NAV = [
{ label: 'START', href: '/', accent: 'var(--color-ink)' },
{ label: 'PROJEKTY', href: '/projekty', accent: 'var(--color-cnc)' },
{ label: 'CNC', href: '/projekty?tag=CNC', accent: 'var(--color-cnc)' },
// ...
]
Pozycja menu może wskazywać na filtr — np. /projekty?tag=WOOD pokaże tylko projekty
z tagiem WOOD. accent to kolor kreski pod pozycją.
Panel → Ustawienia. Te pola widać na stronie publicznej:
| Pole | Gdzie widać |
|---|---|
| Nazwa strony | tytuł w przeglądarce, stopka, dane strukturalne |
| Podpis | pod logo w hero — rozdzielajcie kropką • |
| Hasło w hero | duże zdanie na pierwszym ekranie |
| Opis (SEO) | Google, podglądy linków, sekcja „o nas” |
| E-mail, lokalizacja | stopka i strona „o nas” |
| GitHub, Instagram, YouTube | stopka (puste pole = link się nie pokazuje) |
| Notka w stopce | linijka przy prawach autorskich |
Zmiany widać na stronie w ciągu minuty (strona odświeża treści cyklicznie).
Karty projektów wydają dźwięk mechanizmu przy rozsuwaniu. Przełącznik głośnika jest w nagłówku, wybór zapamiętuje się w przeglądarce. Przy systemowym ustawieniu ograniczonego ruchu dźwięk jest domyślnie wyciszony.
Pliki generuje skrypt: npm run sounds. Parametry brzmienia są opisane
w scripts/generate-sounds.mjs.
Niektóre projekty mają odtwarzacz z przebiegiem fali (ACP/2, AURORA). Plik audio pobiera się dopiero po naciśnięciu play — nic nie gra samo z siebie i nic nie obciąża strony, dopóki ktoś nie kliknie.
Pliki leżą w public/audio/. Żeby dodać własny, wrzućcie tam plik MP3
i poproście programistę o podpięcie odtwarzacza.
Większość dzieje się automatycznie. Wasza rola to trzy pola przy każdym wpisie:
| Pole | Wskazówka |
|---|---|
| Lead / krótki opis | To on trafia do Google, gdy nie wypełnicie opisu SEO |
| SEO — tytuł | Do 60 znaków. Puste = użyty zwykły tytuł. |
| SEO — opis | Do 160 znaków. Puste = użyty lead. |
Automatycznie generowane są: mapa witryny (/sitemap.xml), plik
/robots.txt, podglądy linków dla mediów społecznościowych oraz dane strukturalne
dla wyszukiwarek. Panel i wyszukiwarka są wyłączone z indeksowania.
https://wasza-domena.pl/sitemap.xml
Jedno polecenie kopiuje bazę danych, wszystkie wgrane zdjęcia i konfigurację:
npm run backup
Kopie lądują w backups/RRRR-MM-DD_GG-MM/. Starsze niż 14 dni kasują się same
(BACKUP_KEEP_DAYS zmienia ten okres).
0 3 * * * cd /var/www/szopanawsi && /usr/bin/npm run backup
systemctl stop szopanawsidatabase.db z kopii do prisma/dev.dbuploads z kopii w miejsce istniejącegosystemctl start szopanawsibackups/ kopiujcie regularnie gdzie indziej — na inny komputer,
dysk zewnętrzny albo do chmury. Awaria dysku zabiera oryginał i kopię naraz.
Ten rozdział opisuje rzeczywistą instalację działającą pod adresem
szopanawsi.pl, a nie wariant przykładowy. Strona stoi na tej samej maszynie
co Nextcloud, Jellyfin, Immich i pozostałe usługi domowe, dlatego kilka rozwiązań
odbiega od typowego poradnika — i warto wiedzieć dlaczego.
| Element | Wartość | Dlaczego tak |
|---|---|---|
| Serwer | Ubuntu 24.04 LTS, 192.168.33.34 | ta sama maszyna co reszta usług |
| Katalog | /home/ardmin/szopanawsi | /opt i /var/www wymagają sudo, katalog domowy nie |
| Port | 3005 | 3000 zajmuje inna usługa |
| Serwer WWW | Apache jako odwrotne proxy | na maszynie działa już Apache z kilkunastoma vhostami; dokładanie nginxa oznaczałoby wojnę o porty 80/443 |
| Autostart | cron @reboot | systemd wymaga sudo, a loginctl enable-linger jest wyłączony; cron działa bez uprawnień |
| Certyfikat | Let's Encrypt, www.szopanawsi.pl | przejęty po poprzedniej stronie (Grav) |
Strona jest budowana na serwerze, nie na komputerze. To nie jest kwestia
wygody: Prisma i sharp zawierają biblioteki natywne skompilowane pod konkretny system,
więc paczka złożona na Windows nie uruchomi się na Linuksie. Dlatego wysyłamy źródła
(około 4 MB), a nie gotowy katalog .next (ponad 300 MB).
Z katalogu projektu na komputerze:
DEST=/home/ardmin/szopanawsi PORT=3005 bash deploy/deploy.sh szopa
szopa to wpis w ~/.ssh/config wskazujący na serwer i klucz
szopanawsi_deploy. Skrypt pakuje źródła, wysyła je, instaluje zależności,
generuje klienta Prismy, buduje stronę i restartuje proces.
Domyślnie skrypt nie dotyka bazy ani zdjęć. To zabezpieczenie, nie
niedopatrzenie: treści dodane przez panel /admin istnieją tylko na serwerze
i są nowsze niż kopia lokalna. Nadpisanie ich flagą --with-data jest decyzją
świadomą, a skrypt i tak najpierw odkłada starą bazę do backups/:
DEST=/home/ardmin/szopanawsi PORT=3005 bash deploy/deploy.sh szopa --with-data
| Polecenie | Działanie |
|---|---|
~/szopanawsi/start.sh | uruchamia stronę (nic nie robi, jeśli już działa) |
~/szopanawsi/stop.sh | zatrzymuje, czekając do 10 s na zamknięcie |
tail -f ~/szopanawsi/app.log | podgląd logów na żywo |
cat ~/szopanawsi/app.pid | numer procesu |
crontab -l | sprawdzenie wpisu autostartu |
W katalogu projektu leży wyslij.cmd. Przeciągnij na niego zdjęcia
albo cały folder — trafią do biblioteki mediów i pojawią się w panelu, gotowe do
wstawienia w projekt czy artykuł.
Narzędzie nie potrzebuje SSH ani znajomości adresu serwera: idzie przez publiczne HTTPS, więc działa tak samo w domu, jak i poza nim. Pliki przechodzą tę samą ścieżkę co upload z panelu — przeskalowanie, warianty AVIF i WEBP, sprawdzenie typu — a nie osobną, która mogłaby się z panelem rozjechać.
wyslij.cmd zdjecie.jpg
node deploy/wyslij.mjs C:zdjeciawarsztat
Kod wysyła się jednym poleceniem z trasą auto. Skrypt sam sprawdza po kolei
sieć domową, tailnet i adres publiczny, i używa pierwszej, która odpowiada:
DEST=/home/ardmin/szopanawsi PORT=3005 bash deploy/deploy.sh auto
W domu wybierze szopa-lan, bo jest najszybsza. Poza domem zadziała dopiero
wtedy, gdy serwer będzie w tailnecie — port 22 nie jest już wystawiony na publiczny adres.
Plik deploy/apache-szopanawsi.conf zawiera dwa vhosty: na porcie 80
(przekierowanie na HTTPS plus wyjątek dla odnawiania certyfikatu) i na 443 (proxy na
127.0.0.1:3005). Instalacja wymaga uprawnień administratora:
sudo cp /home/ardmin/szopanawsi/deploy/apache-szopanawsi.conf /etc/apache2/sites-available/szopanawsi.conf
sudo a2ensite szopanawsi
sudo apache2ctl configtest && sudo systemctl reload apache2
Vhost ustawia LimitRequestBody na 32 MB, żeby panel przyjmował duże zdjęcia
z warsztatu, oraz roczny cache dla /_next/static/ i /media/ —
pliki w obu ścieżkach mają w nazwie skrót treści, więc nie zmieniają się w miejscu.
Poprzednia strona (Grav) nie została skasowana — jej pliki leżą w /srv/www/grav,
a konfiguracja pozostaje w sites-available. Powrót zajmuje kilka sekund:
sudo a2dissite szopanawsi && sudo a2ensite grav grav-le-ssl && sudo systemctl reload apache2
Certyfikat www.szopanawsi.pl był wystawiony jeszcze dla vhosta Grava i został
przejęty przez nową konfigurację. Po przełączeniu warto sprawdzić, czy odnawianie nadal
działa — inaczej problem wyjdzie dopiero w dniu wygaśnięcia:
sudo certbot renew --dry-run
Konto administratora przyjeżdża razem z bazą, więc logowanie działa tymi samymi danymi
co lokalnie. Hasło trzeba zmienić, bo strona jest już publiczna —
w panelu /admin, w ustawieniach konta. Pola ADMIN_EMAIL
i ADMIN_PASSWORD w serwerowym .env służą wyłącznie do zakładania
konta przy pustej bazie i nie mają wpływu na logowanie.
Plik .env powstaje na serwerze przy pierwszym wdrożeniu i ma własny,
losowy AUTH_SECRET. Kolejne wdrożenia go nie ruszają — sekret zostaje ten sam,
dzięki czemu sesje zalogowanych osób przeżywają aktualizację.
cd /var/www/szopanawsi
npm run backup # najpierw kopia
git pull
npm ci
npx prisma db push # gdy zmieniła się struktura bazy
npm run build
sudo systemctl restart szopanawsi
sudo journalctl -u szopanawsi -f # na żywo
sudo journalctl -u szopanawsi -n 100 # ostatnie 100 linii
| Element | Rozmiar |
|---|---|
| Kod i zależności | ok. 500 MB |
| Baza danych | kilka MB, rośnie powoli |
Zdjęcia (uploads/) | zależy od Was — każde zdjęcie plus osiem wersji |
| Objaw | Przyczyna i rozwiązanie |
|---|---|
| Nowe zdjęcie się nie pokazuje | Odświeżcie stronę z pominięciem pamięci: Ctrl+F5. Strona odświeża treści co minutę. |
| Wpis opublikowany, ale go nie widać | Sprawdźcie status (musi być „Opublikowany”) i poczekajcie minutę. |
| Nie mogę się zalogować | Po ośmiu błędnych próbach logowanie jest blokowane na 10 minut. Poczekajcie. |
| Wylogowuje po chwili | Sesja trwa 7 dni. Wcześniejsze wylogowanie oznacza zmianę AUTH_SECRET — wszystkie sesje przestają być ważne. |
| Wgrywanie kończy się błędem | Plik większy niż 20 MB albo format inny niż JPG/PNG/WEBP/GIF. Na serwerze sprawdźcie client_max_body_size w nginx. |
| Strona nie startuje po aktualizacji | journalctl -u szopanawsi -n 50 pokaże powód. Najczęściej brak npm run build albo błąd w .env. |
| Edytor nie zapisuje | Sprawdźcie połączenie. Szkic i tak jest zapisywany co 20 s — po odświeżeniu pojawi się propozycja przywrócenia. |
| Zdjęcia wolno się ładują | Upewnijcie się, że nginx obsługuje /media/ bezpośrednio (Krok 4 wdrożenia). |
npm run dev # tryb roboczy
npm run build # budowanie
npm start # uruchomienie
npm run backup # kopia zapasowa
npm run db:studio # podgląd bazy
npm run sounds # dźwięki migawki
npm run typecheck # kontrola kodu
/ — strona główna
/admin — panel
/admin/media — zdjęcia
/admin/ustawienia — ustawienia
/sitemap.xml — mapa witryny
.env — konfiguracja
prisma/dev.db — baza
uploads/ — zdjęcia
backups/ — kopie
docs/DESIGN.md — design system
/ADMIN → ARTYKUŁY → + NOWY ARTYKUŁ → TYTUŁ → LEAD → ZDJĘCIE GŁÓWNE → TREŚĆ → PUBLIKUJ