Find a file
oskar 3e452191de feat: wybór języka przez URL (/en) — reaktywny hook, przełącznik, hreflang
Język wynikał z navigator.language liczonego przy każdym renderze, więc nie
dało się go wybrać ani zalinkować. Teraz nośnikiem języka jest ścieżka.

- src/router.ts: usePathname() na useSyncExternalStore + navigate(). pushState
  nie emituje zdarzenia, więc bez tego React nie widzi zmiany URL-a.
- i18n: useLang(), localizePath(), stripLangPrefix(), setLang(). useT() czyta
  język ze ścieżki i jest reaktywne na nawigację.
- Detekcja przeglądarki tylko przy pierwszym wejściu na "/" i tylko gdy w
  localStorage nic nie ma; wynik zapisujemy od razu, więc przekierowanie na
  /en zadziała najwyżej raz i nie nadpisze późniejszego wyboru użytkownika.
  Deep linki honorujemy bez ruszania.
- App.tsx: jedna tablica tras dla obu języków (/en/privacy -> '/privacy').
  Ustawia też document.documentElement.lang, bo index.html ma na sztywno "pl".
- Header: przełącznik PL/EN (desktop + mobile), <button>, nie <a> — link
  przeładowałby dokument.
- Hrefy w Header/Footer/PrivacyPolicyPage/PlatformPage przez localizePath,
  inaczej /en jest pułapką jednokierunkową: każdy klik wraca na PL.
- index.html: hreflang pl/en/x-default; og:url z gethumanai.com na .pl
  (wskazywał na cudzą domenę).

Bez nowych tłumaczeń treści — to osobny krok.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 15:54:49 +02:00
.junie/memory Initial commit: project structure and header component 2026-05-12 19:09:50 +02:00
mailer Add contact form mailer microservice and i18n support 2026-06-18 15:12:05 +02:00
src feat: wybór języka przez URL (/en) — reaktywny hook, przełącznik, hreflang 2026-07-31 15:54:49 +02:00
.env.example Add contact form mailer microservice and i18n support 2026-06-18 15:12:05 +02:00
.gitignore chore: ignoruj roboczy CONTENT_EXPORT.md 2026-07-31 14:49:06 +02:00
deploy.sh fix deploy.sh: target Hetzner VPS instead of piha.local homelab 2026-06-18 15:22:04 +02:00
Dockerfile feat: dodaj stronę polityki prywatności (PL+EN) z routingiem 2026-06-25 12:53:49 +02:00
index.html feat: wybór języka przez URL (/en) — reaktywny hook, przełącznik, hreflang 2026-07-31 15:54:49 +02:00
nginx.conf feat: dodaj stronę polityki prywatności (PL+EN) z routingiem 2026-06-25 12:53:49 +02:00
package-lock.json Initial commit: project structure and header component 2026-05-12 19:09:50 +02:00
package.json Initial commit: project structure and header component 2026-05-12 19:09:50 +02:00
postcss.config.js Initial commit: project structure and header component 2026-05-12 19:09:50 +02:00
README.md Add contact form mailer microservice and i18n support 2026-06-18 15:12:05 +02:00
tailwind.config.js Initial commit: project structure and header component 2026-05-12 19:09:50 +02:00
tsconfig.json Initial commit: project structure and header component 2026-05-12 19:09:50 +02:00
tsconfig.node.json Initial commit: project structure and header component 2026-05-12 19:09:50 +02:00
vite.config.ts Add Umami analytics tag to <head> on production builds 2026-06-24 17:00:42 +02:00

humanAI — landing page

React + Vite static site, served by nginx in the humanai-landing Docker container, behind Nginx Proxy Manager on the nginxproxymanager_default network.

Development

npm install
npm run dev

Deploy

./deploy.sh

The script builds images locally, pushes them to piha.local via the piha Docker context, and runs smoke tests against the mailer endpoint.

Mailer

The mailer/ directory contains a standalone Express microservice that handles the contact form. It runs as humanai-mailer on the same Docker network as NPM so it can be proxied without exposing any port to the host.

Manual steps required before first deploy

(a) Create a Fastmail app-password and write credentials to mailer.env on the deploy machine:

# mailer.env  (never commit this file)
SMTP_USER=youruser@fastmail.com
SMTP_PASS=your-app-password

(b) In Nginx Proxy Manager → Proxy Host for gethumanai.pl → Custom Locations:

Field Value
location /api
scheme http
forward hostname humanai-mailer
port 3000