refactor(i18n): cała treść landingu i /platforma przez useT()

Krok 1 z dwóch: przenosi stringi, nie tłumaczy ich. en.ts dostaje komplet
kluczy z polską treścią — angielskie wartości wchodzą osobnym commitem, żeby
diff tłumaczeń dało się czytać zdanie po zdaniu.

- data/content.ts: zostaje sama struktura (id, icon, href). Ikony to komponenty
  Reacta i nie mogą wejść do słowników; kolejność i liczba kart są przez to
  zdefiniowane raz, a nie duplikowane per język.
- i18n/types.ts + RichText: akapity z <strong>/<em> w środku zdania trzymamy
  jako listę przebiegów. Bez dangerouslySetInnerHTML — tłumaczenie nie może
  wstrzyknąć znaczników.
- en.ts typowane jako `typeof pl`, więc rozjazd kluczy to błąd builda. Przy
  ~150 kluczach to główne ryzyko tej zmiany.
- privacy.backToHome -> common.backToHome (używane przez obie podstrony).

Weryfikacja: renderowany tekst porównany z produkcją na wszystkich sześciu
trasach — identyczny, poza linkiem powrotnym na /en/platforma, który był
zahardkodowany po polsku i teraz zgadza się z /en/privacy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
oskar 2026-07-31 16:46:46 +02:00
parent 13ffb8754b
commit 605bc3d025
16 changed files with 738 additions and 292 deletions

View file

@ -1,13 +1,10 @@
import React from 'react';
import { motion } from 'framer-motion';
import { CheckCircle2 } from 'lucide-react';
import { useT } from '../i18n';
const About = () => {
const points = [
"Strategia bez hypeu",
"Automatyzacje, które da się utrzymać",
"Agenci pod kontrolą człowieka"
];
const t = useT();
return (
<section id="about" className="py-24 relative overflow-hidden">
@ -19,14 +16,11 @@ const About = () => {
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<h2 className="text-3xl md:text-4xl font-bold mb-8">Czym jest humanAI?</h2>
<p className="text-xl text-muted leading-relaxed mb-12">
humanAI łączy doradztwo, automatyzację, budowę produktów i własne środowisko agentowe.
Pomagamy przejść od ciekawości wokół AI do działających procesów, narzędzi i systemów.
</p>
<h2 className="text-3xl md:text-4xl font-bold mb-8">{t.about.title}</h2>
<p className="text-xl text-muted leading-relaxed mb-12">{t.about.lead}</p>
<div className="grid md:grid-cols-3 gap-6">
{points.map((point, index) => (
{t.about.points.map((point, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 10 }}

View file

@ -1,18 +1,20 @@
import React from 'react';
import { motion } from 'framer-motion';
import { audience } from '../data/content';
import { UserCheck } from 'lucide-react';
import { useT } from '../i18n';
const Audience = () => {
const t = useT();
return (
<section className="py-24 relative overflow-hidden">
<div className="container mx-auto px-6">
<div className="mb-16 text-center">
<h2 className="text-3xl md:text-5xl font-bold mb-6">Dla kogo</h2>
<h2 className="text-3xl md:text-5xl font-bold mb-6">{t.audience.title}</h2>
</div>
<div className="flex flex-wrap justify-center gap-6">
{audience.map((item, index) => (
{t.audience.items.map((item, index) => (
<motion.div
key={index}
initial={{ opacity: 0, scale: 0.9 }}

View file

@ -100,12 +100,8 @@ const CTASection = () => {
<div className="grid md:grid-cols-2 gap-12 relative z-10">
<div>
<h2 className="text-4xl font-bold mb-6">
Masz proces, który powinien już pracować sam?
</h2>
<p className="text-xl text-muted mb-8">
Opowiedz, co robisz ręcznie, powtarzalnie albo zbyt wolno. Sprawdzimy, czy AI może to uprościć.
</p>
<h2 className="text-4xl font-bold mb-6">{t.cta.title}</h2>
<p className="text-xl text-muted mb-8">{t.cta.lead}</p>
<div className="space-y-4">
<div className="flex items-center gap-3 text-primary">
<Mail size={20} />
@ -119,9 +115,7 @@ const CTASection = () => {
support@gethumanai.pl
</a>
</div>
<p className="text-sm text-muted italic">
"Na start wystarczy jeden proces, jeden problem albo jeden pomysł."
</p>
<p className="text-sm text-muted italic">{t.cta.quote}</p>
</div>
</div>

View file

@ -1,9 +1,10 @@
import React from 'react';
import { localizePath, stripLangPrefix, useLang } from '../i18n';
import { localizePath, stripLangPrefix, useLang, useT } from '../i18n';
const Footer = () => {
const currentYear = new Date().getFullYear();
const lang = useLang();
const t = useT();
// Same reasoning as the /#section nav links below: this footer is shared with
// /privacy and /platforma, so the logo needs a real href to get home from
@ -24,9 +25,7 @@ const Footer = () => {
<a href={localizePath('/', lang)} onClick={handleLogoClick} className="text-2xl font-bold tracking-tight mb-4 block">
human<span className="text-primary">AI</span>
</a>
<p className="text-muted max-w-xs mb-6">
ludzka strona AI budujemy praktyczne systemy AI dla ludzi i organizacji.
</p>
<p className="text-muted max-w-xs mb-6">{t.footer.tagline}</p>
<div className="flex flex-col gap-2">
<a href="mailto:hello@gethumanai.pl" className="text-foreground/80 hover:text-primary transition-colors">
hello@gethumanai.pl
@ -38,25 +37,25 @@ const Footer = () => {
</div>
<div>
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">Nawigacja</h4>
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">{t.footer.navHeading}</h4>
<ul className="space-y-4">
<li><a href={localizePath('/#offerings', lang)} className="text-muted hover:text-foreground transition-colors">Oferta</a></li>
<li><a href={localizePath('/platforma', lang)} className="text-muted hover:text-foreground transition-colors">Platforma</a></li>
<li><a href={localizePath('/#contact', lang)} className="text-muted hover:text-foreground transition-colors">Kontakt</a></li>
<li><a href={localizePath('/#offerings', lang)} className="text-muted hover:text-foreground transition-colors">{t.nav.offerings}</a></li>
<li><a href={localizePath('/platforma', lang)} className="text-muted hover:text-foreground transition-colors">{t.nav.platform}</a></li>
<li><a href={localizePath('/#contact', lang)} className="text-muted hover:text-foreground transition-colors">{t.nav.contact}</a></li>
</ul>
</div>
<div>
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">Prywatność</h4>
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">{t.footer.privacyHeading}</h4>
<ul className="space-y-4">
<li><a href={localizePath('/privacy', lang)} className="text-muted hover:text-foreground transition-colors">Polityka prywatności</a></li>
<li><a href={localizePath('/privacy#cookies', lang)} className="text-muted hover:text-foreground transition-colors">Cookies</a></li>
<li><a href={localizePath('/privacy', lang)} className="text-muted hover:text-foreground transition-colors">{t.footer.privacyPolicy}</a></li>
<li><a href={localizePath('/privacy#cookies', lang)} className="text-muted hover:text-foreground transition-colors">{t.footer.cookies}</a></li>
</ul>
</div>
</div>
<div className="pt-8 border-t border-white/5 flex flex-col md:flex-row justify-between items-center gap-4 text-sm text-muted">
<p>© {currentYear} humanAI. Wszelkie prawa zastrzeżone.</p>
<p>© {currentYear} humanAI. {t.footer.rights}</p>
<div className="flex gap-8">
<span className="hover:text-foreground transition-colors cursor-pointer">LinkedIn</span>
<span className="hover:text-foreground transition-colors cursor-pointer">X / Twitter</span>

View file

@ -1,11 +1,12 @@
import React, { useState, useEffect } from 'react';
import { Menu, X } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { localizePath, useLang } from '../i18n';
import { localizePath, useLang, useT } from '../i18n';
import LangSwitcher from './LangSwitcher';
const Header = () => {
const lang = useLang();
const t = useT();
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
@ -19,13 +20,12 @@ const Header = () => {
// Root-relative so the links also work from the standalone pages (/privacy,
// /platforma), where these sections do not exist — and localized so they keep
// the visitor on the language they are currently reading. Labels stay Polish
// until the section copy itself is translated.
// the visitor on the language they are currently reading.
const navLinks = [
{ name: 'Oferta', href: localizePath('/#offerings', lang) },
{ name: 'Platforma', href: localizePath('/platforma', lang) },
{ name: 'Proces', href: localizePath('/#process', lang) },
{ name: 'Kontakt', href: localizePath('/#contact', lang) },
{ name: t.nav.offerings, href: localizePath('/#offerings', lang) },
{ name: t.nav.platform, href: localizePath('/platforma', lang) },
{ name: t.nav.process, href: localizePath('/#process', lang) },
{ name: t.nav.contact, href: localizePath('/#contact', lang) },
];
return (
@ -51,7 +51,7 @@ const Header = () => {
</a>
))}
<a href={localizePath('/#contact', lang)} className="btn-primary text-sm px-5 py-2">
Porozmawiajmy
{t.nav.cta}
</a>
<LangSwitcher />
</nav>
@ -90,7 +90,7 @@ const Header = () => {
className="btn-primary text-center"
onClick={() => setIsMobileMenuOpen(false)}
>
Porozmawiajmy
{t.nav.cta}
</a>
<div className="pt-2 border-t border-white/10">
<LangSwitcher onSwitch={() => setIsMobileMenuOpen(false)} />

View file

@ -1,8 +1,11 @@
import React from 'react';
import { motion } from 'framer-motion';
import { ArrowRight } from 'lucide-react';
import { useT } from '../i18n';
const Hero = () => {
const t = useT();
return (
<section className="relative min-h-screen flex items-center pt-20 overflow-hidden">
{/* Background elements */}
@ -17,18 +20,20 @@ const Hero = () => {
transition={{ duration: 0.6 }}
>
<h1 className="text-5xl md:text-7xl font-extrabold leading-tight mb-6">
Budujemy <span className="text-gradient">ludzką stronę</span> AI
{t.hero.titleBefore}
<span className="text-gradient">{t.hero.titleAccent}</span>
{t.hero.titleAfter}
</h1>
<p className="text-lg md:text-xl text-muted mb-10 max-w-lg leading-relaxed">
Projektujemy i wdrażamy systemy AI, które pomagają ludziom pracować szybciej, mądrzej i spokojniej od automatyzacji po multiagentowe platformy produktowe.
{t.hero.subtitle}
</p>
<div className="flex flex-col sm:flex-row gap-4">
<a href="#contact" className="btn-primary">
Zacznijmy od audytu AI
{t.hero.ctaPrimary}
<ArrowRight className="ml-2" size={20} />
</a>
<a href="#offerings" className="btn-secondary">
Zobacz ofertę
{t.hero.ctaSecondary}
</a>
</div>
</motion.div>

View file

@ -1,11 +1,29 @@
import React from 'react';
import { motion } from 'framer-motion';
import { offerings } from '../data/content';
import type { OfferingId } from '../data/content';
import { localizePath, useLang, useT } from '../i18n';
import { ArrowRight, ChevronRight } from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
const OfferingCard = ({ offering, index }: { offering: any, index: number }) => {
const Icon = offering.icon;
type Copy = {
title: string;
description: string;
points: readonly string[];
linkLabel?: string;
};
const OfferingCard = ({
copy,
icon: Icon,
href,
index,
}: {
copy: Copy;
icon: LucideIcon;
href?: string;
index: number;
}) => {
return (
<motion.div
initial={{ opacity: 0, y: 30 }}
@ -17,24 +35,24 @@ const OfferingCard = ({ offering, index }: { offering: any, index: number }) =>
<div className="w-14 h-14 rounded-xl bg-primary/10 flex items-center justify-center text-primary mb-6 group-hover:scale-110 transition-transform duration-500">
<Icon size={28} />
</div>
<h3 className="text-2xl font-bold mb-4">{offering.title}</h3>
<h3 className="text-2xl font-bold mb-4">{copy.title}</h3>
<p className="text-muted mb-8 leading-relaxed">
{offering.description}
{copy.description}
</p>
<ul className="space-y-3">
{offering.points.map((point: string, i: number) => (
{copy.points.map((point, i) => (
<li key={i} className="flex items-center text-sm text-foreground/80">
<ChevronRight className="text-primary mr-2" size={16} />
{point}
</li>
))}
</ul>
{offering.link && (
{href && copy.linkLabel && (
<a
href={offering.link.href}
href={href}
className="mt-8 inline-flex items-center text-sm font-semibold text-primary hover:underline"
>
{offering.link.label}
{copy.linkLabel}
<ArrowRight className="ml-2" size={16} />
</a>
)}
@ -43,19 +61,29 @@ const OfferingCard = ({ offering, index }: { offering: any, index: number }) =>
};
const Offerings = () => {
const t = useT();
const lang = useLang();
return (
<section id="offerings" className="py-24 relative bg-surface/30">
<div className="container mx-auto px-6">
<div className="mb-16">
<h2 className="text-3xl md:text-5xl font-bold mb-6">Nasza Oferta</h2>
<h2 className="text-3xl md:text-5xl font-bold mb-6">{t.offerings.title}</h2>
<p className="text-xl text-muted max-w-2xl">
Budujemy kompleksowe rozwiązania, które przekładają potencjał sztucznej inteligencji na realne wyniki biznesowe.
{t.offerings.lead}
</p>
</div>
<div className="grid md:grid-cols-2 gap-8">
{offerings.map((offering, index) => (
<OfferingCard key={offering.id} offering={offering} index={index} />
<OfferingCard
key={offering.id}
icon={offering.icon}
// Structure lives in content.ts, copy in i18n — joined by id.
copy={t.offerings.items[offering.id as OfferingId]}
href={'link' in offering ? localizePath(offering.link.href, lang) : undefined}
index={index}
/>
))}
</div>
</div>

View file

@ -1,15 +1,28 @@
import React from 'react';
import { ArrowRight, Building2, CheckCircle2, ChevronRight, Home } from 'lucide-react';
import Footer from './Footer';
import { localizePath, useLang } from '../i18n';
import RichText from './RichText';
import { localizePath, useLang, useT } from '../i18n';
import type { Bullet } from '../i18n/types';
import LangSwitcher from './LangSwitcher';
// Standalone product page at /platforma (and /en/platforma). The copy is not
// localized yet — the site only translates contact.* and privacy.* — but the
// links are, so reaching this page from /en does not strand you in Polish.
// Standalone product page at /platforma (and /en/platforma). All copy lives in
// i18n under `platform`; paragraphs that carry inline emphasis are stored as
// runs and rendered through <RichText> (see i18n/types.ts).
const PlatformPage = () => {
const t = useT();
const lang = useLang();
const renderBullet = (bullet: Bullet, i: number, Icon: typeof ChevronRight) => (
<li key={i} className="flex gap-3">
<Icon className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
{bullet.lead && <strong className="text-foreground font-semibold">{bullet.lead}</strong>}
{bullet.body && <RichText content={bullet.body} />}
</span>
</li>
);
return (
<div className="min-h-screen bg-background selection:bg-primary selection:text-background">
<header className="bg-background/80 backdrop-blur-lg border-b border-white/5">
@ -19,7 +32,7 @@ const PlatformPage = () => {
</a>
<div className="flex items-center gap-6">
<a href={localizePath('/', lang)} className="text-sm text-muted hover:text-foreground transition-colors">
Wróć na stronę główną
{t.common.backToHome}
</a>
<LangSwitcher />
</div>
@ -27,83 +40,42 @@ const PlatformPage = () => {
</header>
<main className="container mx-auto px-6 py-16 max-w-3xl">
<h1 className="text-4xl md:text-5xl font-bold mb-3">Nadzór nad systemami agentowymi</h1>
<p className="text-muted text-sm italic mb-16">
(nazwa robocza do potwierdzenia przed publikacją)
</p>
<h1 className="text-4xl md:text-5xl font-bold mb-3">{t.platform.title}</h1>
<p className="text-muted text-sm italic mb-16">{t.platform.workingName}</p>
<div className="space-y-16">
{/* ── Kto pilnuje agentów ───────────────────────────────────────── */}
<section>
<h2 className="text-2xl md:text-3xl font-bold mb-6">
Kto pilnuje agentów, którzy pilnują wszystkiego innego?
</h2>
<p className="text-foreground/80 leading-relaxed mb-4">
{'Automatyzacje i agenci AI potrafią pracować bez człowieka — porządkować dokumenty, sterować urządzeniami, reagować na zdarzenia. Ale zostawione bez nadzoru, prędzej czy później zrobią coś, czego nikt nie chciał. Zbudowaliśmy system, który '}
<strong className="text-foreground font-semibold">
obserwuje inne systemy w tym inne systemy agentowe
</strong>
{' — wykrywa, że coś nie działa, diagnozuje przyczynę i naprawia problem sam. A tam, gdzie decyzja jest nieodwracalna, czeka na człowieka.'}
</p>
<p className="text-foreground/80 leading-relaxed">
{'To nie koncept. Ten sam rdzeń od miesięcy prowadzi naszą własną, rozproszoną infrastrukturę — i przeszedł przez realne awarie, z których każda coś go nauczyła.'}
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.watchers.title}</h2>
{t.platform.watchers.paragraphs.map((paragraph, i) => (
<p key={i} className="text-foreground/80 leading-relaxed mb-4 last:mb-0">
<RichText content={paragraph} />
</p>
))}
</section>
{/* ── Problem, który znika ──────────────────────────────────────── */}
<section>
<h2 className="text-2xl md:text-3xl font-bold mb-6">Problem, który znika</h2>
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.problem.title}</h2>
<ul className="space-y-4">
<li className="flex gap-3">
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">Autonomia bez ram to ryzyko.</strong>
{' Coś, co może samo otworzyć bramę albo zmienić konfigurację usługi, potrzebuje jasnej granicy: co wolno zrobić samodzielnie, co wymaga zgody człowieka.'}
</span>
</li>
<li className="flex gap-3">
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">Automatyka to nie inteligencja.</strong>
{' Wiele domów i firm ma już systemy, które '}
<em>wykonują</em>
{' polecenia — światła, rolety, bramy, obieg dokumentów. Problem w tym, że nic tego nie '}
<em>rozumie</em>
{': nie kojarzy faktów, nie reaguje na kontekst, nie uczy się.'}
</span>
</li>
<li className="flex gap-3">
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">Wiedza znika.</strong>
{' Dlaczego coś się zepsuło miesiąc temu i co wtedy pomogło? Zwykle ta wiedza siedzi w głowie jednej osoby albo w nieprzeszukiwalnym stosie dokumentów.'}
</span>
</li>
{t.platform.problem.bullets.map((bullet, i) => renderBullet(bullet, i, ChevronRight))}
</ul>
</section>
{/* ── Jak to działa ─────────────────────────────────────────────── */}
<section>
<h2 className="text-2xl md:text-3xl font-bold mb-6">Jak to działa</h2>
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.howItWorks.title}</h2>
<p className="text-foreground/80 leading-relaxed mb-4">
<strong className="text-foreground font-semibold">
Rdzeń nadzoru jeden, wspólny dla wszystkiego.
</strong>
{' Lekki agent na każdej maszynie zgłasza stan usług. Centralny „mózg" buduje z tego pełny obraz sytuacji, wykrywa odchylenia od tego, co powinno działać, i albo naprawia problem sam — jeśli akcja jest bezpieczna — albo pyta człowieka, jeśli nie jest.'}
<RichText content={t.platform.howItWorks.core} />
</p>
<p className="text-foreground/80 leading-relaxed mb-10">
{'To „pytanie człowieka" nie jest teorią. Przykład z życia: system zauważa, że wyjechałeś na weekend, a rolety zostały otwarte. Sam ich nie zamknie — wysyła Ci wiadomość: '}
<em className="text-foreground">{'„Nie zamknąłeś rolet. Zamknąć teraz?"'}</em>
{' Odpisujesz „tak" — i dopiero wtedy system zleca to istniejącej automatyce domowej. Decyzja zawsze należy do Ciebie; wykonanie bierze na siebie system.'}
<RichText content={t.platform.howItWorks.humanAsk} />
</p>
<p className="text-foreground/80 leading-relaxed mb-8">
<strong className="text-foreground font-semibold">
System roboczy budowany pod Ciebie.
</strong>
{' To, co ten nadzór pilnuje, dopasowujemy do konkretnej potrzeby.'}
<RichText content={t.platform.howItWorks.tailored} />
</p>
{/* Dwie ścieżki, jeden rdzeń — karty obok siebie */}
@ -112,11 +84,9 @@ const PlatformPage = () => {
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center text-primary mb-6">
<Home size={24} />
</div>
<h3 className="text-xl font-bold mb-4">Dla domu</h3>
<h3 className="text-xl font-bold mb-4">{t.platform.howItWorks.home.title}</h3>
<p className="text-foreground/80 leading-relaxed">
{'Masz już zautomatyzowany dom — światła, rolety, bramy, klimatyzację — ale to automatyka, nie inteligencja: robi dokładnie to, co jej każesz, i nic więcej. Dokładamy warstwę, która '}
<strong className="text-foreground font-semibold">rozumie kontekst</strong>
{': rozpoznaje Twój samochód po tablicy rejestracyjnej i otwiera bramę, zanim dojedziesz do niej. Widzi na kamerach, że nikogo nie ma w domu, i sama wygasza światła na noc. Zauważa, że wyjechałeś, a coś zostało otwarte — i pyta, zanim cokolwiek zrobi.'}
<RichText content={t.platform.howItWorks.home.body} />
</p>
</div>
@ -124,116 +94,52 @@ const PlatformPage = () => {
<div className="w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center text-secondary mb-6">
<Building2 size={24} />
</div>
<h3 className="text-xl font-bold mb-4">Dla firm</h3>
<h3 className="text-xl font-bold mb-4">{t.platform.howItWorks.business.title}</h3>
<p className="text-foreground/80 leading-relaxed">
{'Masz bałagan w dokumentach, obieg papierowy, który nikogo nie satysfakcjonuje, i dane rozsiane po cudzych chmurach, nad którymi nie masz pełnej kontroli. Budujemy Ci paperless na Twoich własnych serwerach — z własną domeną i autoryzacją, bez uzależnienia od zewnętrznych dostawców chmury. Indeksujemy dokumenty, zdjęcia i korespondencję tak, żeby dało się to przeszukać po sensie, nie po słowach kluczowych. Interfejs — webowy panel, a jeśli to naprawdę pasuje do Twojej firmy, także chatbot — dobieramy do tego, czego faktycznie potrzebujesz, a nie do tego, co akurat modne.'}
<RichText content={t.platform.howItWorks.business.body} />
</p>
</div>
</div>
<p className="text-foreground/80 leading-relaxed mt-8">
{'Obie ścieżki łączy to samo: cała konfiguracja tego, co ma działać, jest zapisana jako kod w repozytorium — każda zmiana ma historię i da się ją cofnąć — i obie działają pod tym samym nadzorem, który pilnuje, żeby nic nie zawiodło po cichu.'}
<RichText content={t.platform.howItWorks.shared} />
</p>
</section>
{/* ── Pod maską ─────────────────────────────────────────────────── */}
<section>
<h2 className="text-2xl md:text-3xl font-bold mb-6">Pod maską dla ciekawych</h2>
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.underTheHood.title}</h2>
<ul className="space-y-4">
<li className="flex gap-3">
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
{'Baza wiedzy nie kończy jako martwy indeks. Nad wyszukiwaniem semantycznym powstaje '}
<strong className="text-foreground font-semibold">
czytelna, kompilowana wiki utrzymywana przez model językowy
</strong>
{' — pliki tekstowe z linkami między pojęciami, które agent czyta i aktualizuje tak jak człowiek utrzymuje kod. Budujemy to na otwartym standardzie (Google OKF), nie na własnym, zamkniętym formacie — żeby wiedza, którą zbudujemy, zawsze zostawała czytelna i przenośna.'}
</span>
</li>
<li className="flex gap-3">
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
{'Do zapytań najpierw sięga tańszy model — droższy dopiero wtedy, gdy sprawa naprawdę tego wymaga. W praktyce: streszczenie całego korpusu dokumentów potrafiło kosztować grosze zamiast dni obliczeń.'}
</span>
</li>
<li className="flex gap-3">
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
{'Nie wszystko musi być online 24 godziny na dobę. Kiedy główna maszyna śpi, zapytania automatycznie przejmuje zapasowy sprzęt — bez przerwy zauważalnej dla użytkownika.'}
</span>
</li>
<li className="flex gap-3">
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
{'System sam odróżnia „usługa nie działa" od „usługa śpi zgodnie z planem" — co wcześniej było częstym źródłem fałszywych alarmów.'}
</span>
</li>
{t.platform.underTheHood.bullets.map((bullet, i) => renderBullet(bullet, i, ChevronRight))}
</ul>
</section>
{/* ── Dlaczego to ───────────────────────────────────────────────── */}
<section>
<h2 className="text-2xl md:text-3xl font-bold mb-6">
Dlaczego to, a nie zwykły monitoring czy zwykła automatyka
</h2>
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.why.title}</h2>
<ul className="space-y-4">
<li className="flex gap-3">
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">
Rozumiemy kontekst, nie tylko wykonujemy polecenia.
</strong>
</span>
</li>
<li className="flex gap-3">
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">Naprawiamy, nie tylko alarmujemy.</strong>
</span>
</li>
<li className="flex gap-3">
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">Człowiek naprawdę jest w pętli</strong>
{' — decyzje zawsze do Ciebie, wykonanie bierze na siebie system.'}
</span>
</li>
<li className="flex gap-3">
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">Zero czarnej skrzynki.</strong>
{' Każda decyzja zostawia ślad, który można później przejrzeć.'}
</span>
</li>
<li className="flex gap-3">
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
<span className="text-foreground/80 leading-relaxed">
<strong className="text-foreground font-semibold">Twoje dane zostają Twoje</strong>
{' — własny serwer, własna domena, bez uzależnienia od cudzej chmury.'}
</span>
</li>
{t.platform.why.bullets.map((bullet, i) => renderBullet(bullet, i, CheckCircle2))}
</ul>
</section>
{/* ── Gdzie jesteśmy ────────────────────────────────────────────── */}
<section>
<h2 className="text-2xl md:text-3xl font-bold mb-6">Uczciwie o tym, gdzie jesteśmy</h2>
<p className="text-foreground/80 leading-relaxed mb-4">
{'Rdzeń nadzoru prowadzi naszą infrastrukturę na co dzień — samonaprawa działa od początku do końca, alerty trafiają na telefon, baza wiedzy odpowiada na pytania nawet gdy główny sprzęt śpi.'}
</p>
<p className="text-foreground/80 leading-relaxed">
{'Dedykowane wdrożenia — pod konkretny dom czy firmę — budujemy w miarę potrzeb, opierając się na tym samym, sprawdzonym rdzeniu. Wolimy powiedzieć wprost, co jeszcze dopracowujemy, niż obiecywać więcej niż działa.'}
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.status.title}</h2>
{t.platform.status.paragraphs.map((paragraph, i) => (
<p key={i} className="text-foreground/80 leading-relaxed mb-4 last:mb-0">
<RichText content={paragraph} />
</p>
))}
</section>
{/* ── CTA ───────────────────────────────────────────────────────── */}
<section className="glass-card p-10 text-center">
<h2 className="text-2xl md:text-3xl font-bold mb-6">Umów rozmowę</h2>
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.cta.title}</h2>
<p className="text-foreground/80 leading-relaxed mb-8">
{'Powiedz, co chcesz zautomatyzować albo uporządkować — zobaczymy, jak to zbudować i objąć nadzorem, który sami na sobie testujemy.'}
<RichText content={t.platform.cta.body} />
</p>
<a href={localizePath('/#contact', lang)} className="btn-primary">
Porozmawiajmy
{t.platform.cta.button}
<ArrowRight className="ml-2" size={20} />
</a>
</section>

View file

@ -17,7 +17,7 @@ const PrivacyPolicyPage = () => {
</a>
<div className="flex items-center gap-6">
<a href={home} className="text-sm text-muted hover:text-foreground transition-colors">
{t.privacy.backToHome}
{t.common.backToHome}
</a>
<LangSwitcher />
</div>

View file

@ -1,13 +1,16 @@
import React from 'react';
import { motion } from 'framer-motion';
import { processSteps } from '../data/content';
import { useT } from '../i18n';
const Process = () => {
const t = useT();
return (
<section id="process" className="py-24 relative bg-surface/50">
<div className="container mx-auto px-6">
<div className="text-center mb-16">
<h2 className="text-3xl md:text-5xl font-bold mb-6">Od pomysłu do działającego systemu</h2>
<h2 className="text-3xl md:text-5xl font-bold mb-6">{t.process.title}</h2>
</div>
<div className="relative">
@ -30,8 +33,10 @@ const Process = () => {
<Icon size={28} />
</div>
<div className="text-center">
<span className="text-xs font-bold text-primary uppercase tracking-wider mb-2 block">Krok {step.id}</span>
<h3 className="text-xl font-bold">{step.title}</h3>
<span className="text-xs font-bold text-primary uppercase tracking-wider mb-2 block">
{t.process.stepLabel} {step.number}
</span>
<h3 className="text-xl font-bold">{t.process.steps[step.id]}</h3>
</div>
</motion.div>
);

View file

@ -0,0 +1,36 @@
import React from 'react';
import type { Rich } from '../i18n/types';
/**
* Renders copy that carries inline emphasis (see i18n/types.ts). Keeps the
* dictionaries free of markup: no dangerouslySetInnerHTML, so a translation can
* never inject elements.
*/
const RichText = ({ content }: { content: Rich }) => {
if (typeof content === 'string') return <>{content}</>;
return (
<>
{content.map((run, i) => {
if (run.em === 'strong') {
return (
<strong key={i} className="text-foreground font-semibold">
{run.t}
</strong>
);
}
if (run.em === 'quote') {
return (
<em key={i} className="text-foreground">
{run.t}
</em>
);
}
if (run.em === 'em') return <em key={i}>{run.t}</em>;
return <React.Fragment key={i}>{run.t}</React.Fragment>;
})}
</>
);
};
export default RichText;

View file

@ -1,8 +1,11 @@
import React from 'react';
import { motion } from 'framer-motion';
import { whyHumanAI } from '../data/content';
import { useT } from '../i18n';
const WhyHumanAI = () => {
const t = useT();
return (
<section className="py-24 relative overflow-hidden">
<div className="container mx-auto px-6">
@ -13,7 +16,7 @@ const WhyHumanAI = () => {
viewport={{ once: true }}
className="text-3xl md:text-5xl font-bold mb-8"
>
AI nie powinno być czarną skrzynką
{t.why.title}
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
@ -22,8 +25,7 @@ const WhyHumanAI = () => {
transition={{ delay: 0.1 }}
className="text-xl text-muted leading-relaxed"
>
Najlepsze wdrożenia AI zrozumiałe, mierzalne i bezpieczne. Dlatego projektujemy systemy,
które pokazują swoje działanie, zostawiają ślad decyzyjny i pozwalają człowiekowi zatwierdzać ważne kroki.
{t.why.lead}
</motion.p>
</div>
@ -32,7 +34,7 @@ const WhyHumanAI = () => {
const Icon = item.icon;
return (
<motion.div
key={index}
key={item.id}
initial={{ opacity: 0, scale: 0.9 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
@ -42,7 +44,7 @@ const WhyHumanAI = () => {
<div className="w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center text-secondary mb-6 group-hover:bg-secondary/20 transition-colors">
<Icon size={24} />
</div>
<h3 className="font-semibold text-lg">{item.title}</h3>
<h3 className="font-semibold text-lg">{t.why.items[item.id]}</h3>
</motion.div>
);
})}

View file

@ -8,76 +8,39 @@ import {
ShieldCheck,
BarChart3,
Layout,
MessageSquare,
Eye,
Settings,
Rocket
Rocket,
} from 'lucide-react';
// Structure only — no copy. Icons are React components and cannot live in the
// dictionaries without pulling React into them, and ids/hrefs are not
// translatable anyway. The matching text lives in i18n under the same id, so
// order and cardinality are defined once here rather than duplicated per
// language.
export const offerings = [
{
id: 'strategy',
title: 'AI Strategy & Advisory',
description: 'Pomagamy znaleźć realne zastosowania AI w firmie, wybrać priorytety i zaplanować wdrożenia bez przepalania czasu na przypadkowe eksperymenty.',
points: ['audyt procesów', 'mapa use caseów', 'priorytetyzacja wdrożeń', 'polityki bezpieczeństwa AI'],
icon: Search
},
{
id: 'automation',
title: 'AI Automation & Workflows',
description: 'Budujemy automatyzacje, które łączą modele AI z codziennymi narzędziami: dokumentami, mailem, CRM, bazami danych, API i wewnętrznymi procesami.',
points: ['automatyzacje operacyjne', 'integracje API', 'workflow z człowiekiem w pętli', 'monitoring i logi'],
icon: Workflow
},
{
id: 'products',
title: 'AI Products & Interfaces',
description: 'Projektujemy i tworzymy aplikacje, panele, chatboty, copilots i wyszukiwarki semantyczne, które przekładają AI na użyteczne doświadczenie użytkownika.',
points: ['aplikacje webowe', 'panele AI', 'chatboty i copilots', 'RAG / wyszukiwanie w wiedzy'],
icon: Layout
},
{
id: 'multiagent',
title: 'Multiagent Systems & Infrastructure',
description: 'Tworzymy systemy wieloagentowe, które potrafią planować, wykonywać zadania, korzystać z narzędzi i współpracować z człowiekiem przy zachowaniu kontroli i audytowalności.',
points: ['agent orchestration', 'tool registry / MCP', 'approval gates', 'pamięć, logi i obserwowalność'],
icon: Cpu,
// Deep-link to the dedicated product page (/platforma).
link: { label: 'Zobacz jak to działa', href: '/platforma' }
}
];
{ id: 'strategy', icon: Search },
{ id: 'automation', icon: Workflow },
{ id: 'products', icon: Layout },
// Deep-link to the dedicated product page; the label is translated.
{ id: 'multiagent', icon: Cpu, link: { href: '/platforma' } },
] as const;
export type OfferingId = (typeof offerings)[number]['id'];
export const whyHumanAI = [
{
title: 'Human-in-the-loop',
icon: Users
},
{
title: 'Bezpieczeństwo od początku',
icon: ShieldCheck
},
{
title: 'Integracja z istniejącymi narzędziami',
icon: Layers
},
{
title: 'Mierzalny efekt biznesowy',
icon: BarChart3
}
];
{ id: 'hitl', icon: Users },
{ id: 'security', icon: ShieldCheck },
{ id: 'integration', icon: Layers },
{ id: 'impact', icon: BarChart3 },
] as const;
export type WhyId = (typeof whyHumanAI)[number]['id'];
export const processSteps = [
{ id: 1, title: 'Diagnoza', icon: Eye },
{ id: 2, title: 'Projekt rozwiązania', icon: Layout },
{ id: 3, title: 'Prototyp', icon: Zap },
{ id: 4, title: 'Wdrożenie', icon: Rocket },
{ id: 5, title: 'Utrzymanie i rozwój', icon: Settings }
];
export const audience = [
'founderzy i małe zespoły',
'firmy usługowe',
'działy operacyjne',
'zespoły produktowe',
'software housey i integratorzy'
];
{ id: 'diagnosis', number: 1, icon: Eye },
{ id: 'design', number: 2, icon: Layout },
{ id: 'prototype', number: 3, icon: Zap },
{ id: 'deployment', number: 4, icon: Rocket },
{ id: 'maintenance', number: 5, icon: Settings },
] as const;
export type StepId = (typeof processSteps)[number]['id'];

View file

@ -1,4 +1,122 @@
export const en = {
import type { Bullet, Rich } from './types';
import type { pl } from './pl';
// Step 1 of the i18n rollout: the keys are in place, the values are still the
// Polish source text. Translating them is the next commit — this file's diff is
// then purely textual and reviewable sentence by sentence.
export const en: typeof pl = {
nav: {
offerings: 'Oferta',
platform: 'Platforma',
process: 'Proces',
contact: 'Kontakt',
cta: 'Porozmawiajmy',
},
common: {
backToHome: '← Back to homepage',
},
hero: {
// Split so the accent span can wrap a different phrase per language.
titleBefore: 'Budujemy ',
titleAccent: 'ludzką stronę',
titleAfter: ' AI',
subtitle:
'Projektujemy i wdrażamy systemy AI, które pomagają ludziom pracować szybciej, mądrzej i spokojniej — od automatyzacji po multiagentowe platformy produktowe.',
ctaPrimary: 'Zacznijmy od audytu AI',
ctaSecondary: 'Zobacz ofertę',
},
about: {
title: 'Czym jest humanAI?',
lead: 'humanAI łączy doradztwo, automatyzację, budowę produktów i własne środowisko agentowe. Pomagamy przejść od ciekawości wokół AI do działających procesów, narzędzi i systemów.',
points: [
'Strategia bez hypeu',
'Automatyzacje, które da się utrzymać',
'Agenci pod kontrolą człowieka',
],
},
offerings: {
title: 'Nasza Oferta',
lead: 'Budujemy kompleksowe rozwiązania, które przekładają potencjał sztucznej inteligencji na realne wyniki biznesowe.',
// Service names stay identical across languages, but are kept as per-language
// keys so they can diverge later without a refactor.
items: {
strategy: {
title: 'AI Strategy & Advisory',
description:
'Pomagamy znaleźć realne zastosowania AI w firmie, wybrać priorytety i zaplanować wdrożenia bez przepalania czasu na przypadkowe eksperymenty.',
points: ['audyt procesów', 'mapa use caseów', 'priorytetyzacja wdrożeń', 'polityki bezpieczeństwa AI'],
},
automation: {
title: 'AI Automation & Workflows',
description:
'Budujemy automatyzacje, które łączą modele AI z codziennymi narzędziami: dokumentami, mailem, CRM, bazami danych, API i wewnętrznymi procesami.',
points: ['automatyzacje operacyjne', 'integracje API', 'workflow z człowiekiem w pętli', 'monitoring i logi'],
},
products: {
title: 'AI Products & Interfaces',
description:
'Projektujemy i tworzymy aplikacje, panele, chatboty, copilots i wyszukiwarki semantyczne, które przekładają AI na użyteczne doświadczenie użytkownika.',
points: ['aplikacje webowe', 'panele AI', 'chatboty i copilots', 'RAG / wyszukiwanie w wiedzy'],
},
multiagent: {
title: 'Multiagent Systems & Infrastructure',
description:
'Tworzymy systemy wieloagentowe, które potrafią planować, wykonywać zadania, korzystać z narzędzi i współpracować z człowiekiem przy zachowaniu kontroli i audytowalności.',
points: ['agent orchestration', 'tool registry / MCP', 'approval gates', 'pamięć, logi i obserwowalność'],
linkLabel: 'Zobacz jak to działa',
},
},
},
why: {
title: 'AI nie powinno być czarną skrzynką',
lead: 'Najlepsze wdrożenia AI są zrozumiałe, mierzalne i bezpieczne. Dlatego projektujemy systemy, które pokazują swoje działanie, zostawiają ślad decyzyjny i pozwalają człowiekowi zatwierdzać ważne kroki.',
items: {
hitl: 'Human-in-the-loop',
security: 'Bezpieczeństwo od początku',
integration: 'Integracja z istniejącymi narzędziami',
impact: 'Mierzalny efekt biznesowy',
},
},
process: {
title: 'Od pomysłu do działającego systemu',
stepLabel: 'Krok',
steps: {
diagnosis: 'Diagnoza',
design: 'Projekt rozwiązania',
prototype: 'Prototyp',
deployment: 'Wdrożenie',
maintenance: 'Utrzymanie i rozwój',
},
},
audience: {
title: 'Dla kogo',
items: [
'founderzy i małe zespoły',
'firmy usługowe',
'działy operacyjne',
'zespoły produktowe',
'software housey i integratorzy',
],
},
cta: {
title: 'Masz proces, który powinien już pracować sam?',
lead: 'Opowiedz, co robisz ręcznie, powtarzalnie albo zbyt wolno. Sprawdzimy, czy AI może to uprościć.',
quote: '"Na start wystarczy jeden proces, jeden problem albo jeden pomysł."',
},
footer: {
tagline: 'ludzka strona AI — budujemy praktyczne systemy AI dla ludzi i organizacji.',
navHeading: 'Nawigacja',
privacyHeading: 'Prywatność',
privacyPolicy: 'Polityka prywatności',
cookies: 'Cookies',
rights: 'Wszelkie prawa zastrzeżone.',
},
meta: {
title: 'humanAI — ludzka strona AI',
description:
'Strategia, automatyzacje, produkty AI i systemy multiagentowe projektowane z człowiekiem w centrum.',
},
contact: {
labelName: 'Name',
placeholderName: 'Your name',
@ -25,7 +143,6 @@ export const en = {
title: 'Privacy Policy',
lastUpdated: 'Last updated: June 2026',
intro: 'This privacy policy describes how humanAI (gethumanai.pl) processes personal data and protects the privacy of its users.',
backToHome: '← Back to homepage',
sections: [
{
title: '1. Data Controller',
@ -53,4 +170,137 @@ export const en = {
},
],
},
platform: {
title: 'Nadzór nad systemami agentowymi',
workingName: '(nazwa robocza — do potwierdzenia przed publikacją)',
watchers: {
title: 'Kto pilnuje agentów, którzy pilnują wszystkiego innego?',
paragraphs: [
[
{
t: 'Automatyzacje i agenci AI potrafią pracować bez człowieka — porządkować dokumenty, sterować urządzeniami, reagować na zdarzenia. Ale zostawione bez nadzoru, prędzej czy później zrobią coś, czego nikt nie chciał. Zbudowaliśmy system, który ',
},
{ t: 'obserwuje inne systemy — w tym inne systemy agentowe', em: 'strong' },
{
t: ' — wykrywa, że coś nie działa, diagnozuje przyczynę i naprawia problem sam. A tam, gdzie decyzja jest nieodwracalna, czeka na człowieka.',
},
],
'To nie koncept. Ten sam rdzeń od miesięcy prowadzi naszą własną, rozproszoną infrastrukturę — i przeszedł przez realne awarie, z których każda coś go nauczyła.',
] as Rich[],
},
problem: {
title: 'Problem, który znika',
bullets: [
{
lead: 'Autonomia bez ram to ryzyko.',
body: ' Coś, co może samo otworzyć bramę albo zmienić konfigurację usługi, potrzebuje jasnej granicy: co wolno zrobić samodzielnie, co wymaga zgody człowieka.',
},
{
lead: 'Automatyka to nie inteligencja.',
body: [
{ t: ' Wiele domów i firm ma już systemy, które ' },
{ t: 'wykonują', em: 'em' },
{ t: ' polecenia — światła, rolety, bramy, obieg dokumentów. Problem w tym, że nic tego nie ' },
{ t: 'rozumie', em: 'em' },
{ t: ': nie kojarzy faktów, nie reaguje na kontekst, nie uczy się.' },
],
},
{
lead: 'Wiedza znika.',
body: ' Dlaczego coś się zepsuło miesiąc temu i co wtedy pomogło? Zwykle ta wiedza siedzi w głowie jednej osoby albo w nieprzeszukiwalnym stosie dokumentów.',
},
] as Bullet[],
},
howItWorks: {
title: 'Jak to działa',
core: [
{ t: 'Rdzeń nadzoru — jeden, wspólny dla wszystkiego.', em: 'strong' },
{
t: ' Lekki agent na każdej maszynie zgłasza stan usług. Centralny „mózg" buduje z tego pełny obraz sytuacji, wykrywa odchylenia od tego, co powinno działać, i albo naprawia problem sam — jeśli akcja jest bezpieczna — albo pyta człowieka, jeśli nie jest.',
},
] as Rich,
humanAsk: [
{
t: 'To „pytanie człowieka" nie jest teorią. Przykład z życia: system zauważa, że wyjechałeś na weekend, a rolety zostały otwarte. Sam ich nie zamknie — wysyła Ci wiadomość: ',
},
{ t: '„Nie zamknąłeś rolet. Zamknąć teraz?"', em: 'quote' },
{
t: ' Odpisujesz „tak" — i dopiero wtedy system zleca to istniejącej automatyce domowej. Decyzja zawsze należy do Ciebie; wykonanie bierze na siebie system.',
},
] as Rich,
tailored: [
{ t: 'System roboczy — budowany pod Ciebie.', em: 'strong' },
{ t: ' To, co ten nadzór pilnuje, dopasowujemy do konkretnej potrzeby.' },
] as Rich,
home: {
title: 'Dla domu',
body: [
{
t: 'Masz już zautomatyzowany dom — światła, rolety, bramy, klimatyzację — ale to automatyka, nie inteligencja: robi dokładnie to, co jej każesz, i nic więcej. Dokładamy warstwę, która ',
},
{ t: 'rozumie kontekst', em: 'strong' },
{
t: ': rozpoznaje Twój samochód po tablicy rejestracyjnej i otwiera bramę, zanim dojedziesz do niej. Widzi na kamerach, że nikogo nie ma w domu, i sama wygasza światła na noc. Zauważa, że wyjechałeś, a coś zostało otwarte — i pyta, zanim cokolwiek zrobi.',
},
] as Rich,
},
business: {
title: 'Dla firm',
body: 'Masz bałagan w dokumentach, obieg papierowy, który nikogo nie satysfakcjonuje, i dane rozsiane po cudzych chmurach, nad którymi nie masz pełnej kontroli. Budujemy Ci paperless na Twoich własnych serwerach — z własną domeną i autoryzacją, bez uzależnienia od zewnętrznych dostawców chmury. Indeksujemy dokumenty, zdjęcia i korespondencję tak, żeby dało się to przeszukać po sensie, nie po słowach kluczowych. Interfejs — webowy panel, a jeśli to naprawdę pasuje do Twojej firmy, także chatbot — dobieramy do tego, czego faktycznie potrzebujesz, a nie do tego, co akurat modne.' as Rich,
},
shared:
'Obie ścieżki łączy to samo: cała konfiguracja tego, co ma działać, jest zapisana jako kod w repozytorium — każda zmiana ma historię i da się ją cofnąć — i obie działają pod tym samym nadzorem, który pilnuje, żeby nic nie zawiodło po cichu.' as Rich,
},
underTheHood: {
title: 'Pod maską — dla ciekawych',
bullets: [
{
body: [
{ t: 'Baza wiedzy nie kończy jako martwy indeks. Nad wyszukiwaniem semantycznym powstaje ' },
{ t: 'czytelna, kompilowana wiki utrzymywana przez model językowy', em: 'strong' },
{
t: ' — pliki tekstowe z linkami między pojęciami, które agent czyta i aktualizuje tak jak człowiek utrzymuje kod. Budujemy to na otwartym standardzie (Google OKF), nie na własnym, zamkniętym formacie — żeby wiedza, którą zbudujemy, zawsze zostawała czytelna i przenośna.',
},
],
},
{
body: 'Do zapytań najpierw sięga tańszy model — droższy dopiero wtedy, gdy sprawa naprawdę tego wymaga. W praktyce: streszczenie całego korpusu dokumentów potrafiło kosztować grosze zamiast dni obliczeń.',
},
{
body: 'Nie wszystko musi być online 24 godziny na dobę. Kiedy główna maszyna śpi, zapytania automatycznie przejmuje zapasowy sprzęt — bez przerwy zauważalnej dla użytkownika.',
},
{
body: 'System sam odróżnia „usługa nie działa" od „usługa śpi zgodnie z planem" — co wcześniej było częstym źródłem fałszywych alarmów.',
},
] as Bullet[],
},
why: {
title: 'Dlaczego to, a nie zwykły monitoring czy zwykła automatyka',
bullets: [
{ lead: 'Rozumiemy kontekst, nie tylko wykonujemy polecenia.' },
{ lead: 'Naprawiamy, nie tylko alarmujemy.' },
{
lead: 'Człowiek naprawdę jest w pętli',
body: ' — decyzje zawsze do Ciebie, wykonanie bierze na siebie system.',
},
{ lead: 'Zero czarnej skrzynki.', body: ' Każda decyzja zostawia ślad, który można później przejrzeć.' },
{
lead: 'Twoje dane zostają Twoje',
body: ' — własny serwer, własna domena, bez uzależnienia od cudzej chmury.',
},
] as Bullet[],
},
status: {
title: 'Uczciwie o tym, gdzie jesteśmy',
paragraphs: [
'Rdzeń nadzoru prowadzi naszą infrastrukturę na co dzień — samonaprawa działa od początku do końca, alerty trafiają na telefon, baza wiedzy odpowiada na pytania nawet gdy główny sprzęt śpi.',
'Dedykowane wdrożenia — pod konkretny dom czy firmę — budujemy w miarę potrzeb, opierając się na tym samym, sprawdzonym rdzeniu. Wolimy powiedzieć wprost, co jeszcze dopracowujemy, niż obiecywać więcej niż działa.',
] as Rich[],
},
cta: {
title: 'Umów rozmowę',
body: 'Powiedz, co chcesz zautomatyzować albo uporządkować — zobaczymy, jak to zbudować i objąć nadzorem, który sami na sobie testujemy.' as Rich,
button: 'Porozmawiajmy',
},
},
};

View file

@ -1,4 +1,117 @@
import type { Bullet, Rich } from './types';
export const pl = {
nav: {
offerings: 'Oferta',
platform: 'Platforma',
process: 'Proces',
contact: 'Kontakt',
cta: 'Porozmawiajmy',
},
common: {
backToHome: '← Wróć na stronę główną',
},
hero: {
// Split so the accent span can wrap a different phrase per language.
titleBefore: 'Budujemy ',
titleAccent: 'ludzką stronę',
titleAfter: ' AI',
subtitle:
'Projektujemy i wdrażamy systemy AI, które pomagają ludziom pracować szybciej, mądrzej i spokojniej — od automatyzacji po multiagentowe platformy produktowe.',
ctaPrimary: 'Zacznijmy od audytu AI',
ctaSecondary: 'Zobacz ofertę',
},
about: {
title: 'Czym jest humanAI?',
lead: 'humanAI łączy doradztwo, automatyzację, budowę produktów i własne środowisko agentowe. Pomagamy przejść od ciekawości wokół AI do działających procesów, narzędzi i systemów.',
points: [
'Strategia bez hypeu',
'Automatyzacje, które da się utrzymać',
'Agenci pod kontrolą człowieka',
],
},
offerings: {
title: 'Nasza Oferta',
lead: 'Budujemy kompleksowe rozwiązania, które przekładają potencjał sztucznej inteligencji na realne wyniki biznesowe.',
// Service names stay identical across languages, but are kept as per-language
// keys so they can diverge later without a refactor.
items: {
strategy: {
title: 'AI Strategy & Advisory',
description:
'Pomagamy znaleźć realne zastosowania AI w firmie, wybrać priorytety i zaplanować wdrożenia bez przepalania czasu na przypadkowe eksperymenty.',
points: ['audyt procesów', 'mapa use caseów', 'priorytetyzacja wdrożeń', 'polityki bezpieczeństwa AI'],
},
automation: {
title: 'AI Automation & Workflows',
description:
'Budujemy automatyzacje, które łączą modele AI z codziennymi narzędziami: dokumentami, mailem, CRM, bazami danych, API i wewnętrznymi procesami.',
points: ['automatyzacje operacyjne', 'integracje API', 'workflow z człowiekiem w pętli', 'monitoring i logi'],
},
products: {
title: 'AI Products & Interfaces',
description:
'Projektujemy i tworzymy aplikacje, panele, chatboty, copilots i wyszukiwarki semantyczne, które przekładają AI na użyteczne doświadczenie użytkownika.',
points: ['aplikacje webowe', 'panele AI', 'chatboty i copilots', 'RAG / wyszukiwanie w wiedzy'],
},
multiagent: {
title: 'Multiagent Systems & Infrastructure',
description:
'Tworzymy systemy wieloagentowe, które potrafią planować, wykonywać zadania, korzystać z narzędzi i współpracować z człowiekiem przy zachowaniu kontroli i audytowalności.',
points: ['agent orchestration', 'tool registry / MCP', 'approval gates', 'pamięć, logi i obserwowalność'],
linkLabel: 'Zobacz jak to działa',
},
},
},
why: {
title: 'AI nie powinno być czarną skrzynką',
lead: 'Najlepsze wdrożenia AI są zrozumiałe, mierzalne i bezpieczne. Dlatego projektujemy systemy, które pokazują swoje działanie, zostawiają ślad decyzyjny i pozwalają człowiekowi zatwierdzać ważne kroki.',
items: {
hitl: 'Human-in-the-loop',
security: 'Bezpieczeństwo od początku',
integration: 'Integracja z istniejącymi narzędziami',
impact: 'Mierzalny efekt biznesowy',
},
},
process: {
title: 'Od pomysłu do działającego systemu',
stepLabel: 'Krok',
steps: {
diagnosis: 'Diagnoza',
design: 'Projekt rozwiązania',
prototype: 'Prototyp',
deployment: 'Wdrożenie',
maintenance: 'Utrzymanie i rozwój',
},
},
audience: {
title: 'Dla kogo',
items: [
'founderzy i małe zespoły',
'firmy usługowe',
'działy operacyjne',
'zespoły produktowe',
'software housey i integratorzy',
],
},
cta: {
title: 'Masz proces, który powinien już pracować sam?',
lead: 'Opowiedz, co robisz ręcznie, powtarzalnie albo zbyt wolno. Sprawdzimy, czy AI może to uprościć.',
quote: '"Na start wystarczy jeden proces, jeden problem albo jeden pomysł."',
},
footer: {
tagline: 'ludzka strona AI — budujemy praktyczne systemy AI dla ludzi i organizacji.',
navHeading: 'Nawigacja',
privacyHeading: 'Prywatność',
privacyPolicy: 'Polityka prywatności',
cookies: 'Cookies',
rights: 'Wszelkie prawa zastrzeżone.',
},
meta: {
title: 'humanAI — ludzka strona AI',
description:
'Strategia, automatyzacje, produkty AI i systemy multiagentowe projektowane z człowiekiem w centrum.',
},
contact: {
labelName: 'Imię',
placeholderName: 'Twoje imię',
@ -25,7 +138,6 @@ export const pl = {
title: 'Polityka prywatności',
lastUpdated: 'Ostatnia aktualizacja: czerwiec 2026',
intro: 'Niniejsza polityka prywatności opisuje, w jaki sposób humanAI (gethumanai.pl) przetwarza dane osobowe i dba o prywatność użytkowników.',
backToHome: '← Wróć na stronę główną',
sections: [
{
title: '1. Administrator danych',
@ -53,4 +165,137 @@ export const pl = {
},
],
},
platform: {
title: 'Nadzór nad systemami agentowymi',
workingName: '(nazwa robocza — do potwierdzenia przed publikacją)',
watchers: {
title: 'Kto pilnuje agentów, którzy pilnują wszystkiego innego?',
paragraphs: [
[
{
t: 'Automatyzacje i agenci AI potrafią pracować bez człowieka — porządkować dokumenty, sterować urządzeniami, reagować na zdarzenia. Ale zostawione bez nadzoru, prędzej czy później zrobią coś, czego nikt nie chciał. Zbudowaliśmy system, który ',
},
{ t: 'obserwuje inne systemy — w tym inne systemy agentowe', em: 'strong' },
{
t: ' — wykrywa, że coś nie działa, diagnozuje przyczynę i naprawia problem sam. A tam, gdzie decyzja jest nieodwracalna, czeka na człowieka.',
},
],
'To nie koncept. Ten sam rdzeń od miesięcy prowadzi naszą własną, rozproszoną infrastrukturę — i przeszedł przez realne awarie, z których każda coś go nauczyła.',
] as Rich[],
},
problem: {
title: 'Problem, który znika',
bullets: [
{
lead: 'Autonomia bez ram to ryzyko.',
body: ' Coś, co może samo otworzyć bramę albo zmienić konfigurację usługi, potrzebuje jasnej granicy: co wolno zrobić samodzielnie, co wymaga zgody człowieka.',
},
{
lead: 'Automatyka to nie inteligencja.',
body: [
{ t: ' Wiele domów i firm ma już systemy, które ' },
{ t: 'wykonują', em: 'em' },
{ t: ' polecenia — światła, rolety, bramy, obieg dokumentów. Problem w tym, że nic tego nie ' },
{ t: 'rozumie', em: 'em' },
{ t: ': nie kojarzy faktów, nie reaguje na kontekst, nie uczy się.' },
],
},
{
lead: 'Wiedza znika.',
body: ' Dlaczego coś się zepsuło miesiąc temu i co wtedy pomogło? Zwykle ta wiedza siedzi w głowie jednej osoby albo w nieprzeszukiwalnym stosie dokumentów.',
},
] as Bullet[],
},
howItWorks: {
title: 'Jak to działa',
core: [
{ t: 'Rdzeń nadzoru — jeden, wspólny dla wszystkiego.', em: 'strong' },
{
t: ' Lekki agent na każdej maszynie zgłasza stan usług. Centralny „mózg" buduje z tego pełny obraz sytuacji, wykrywa odchylenia od tego, co powinno działać, i albo naprawia problem sam — jeśli akcja jest bezpieczna — albo pyta człowieka, jeśli nie jest.',
},
] as Rich,
humanAsk: [
{
t: 'To „pytanie człowieka" nie jest teorią. Przykład z życia: system zauważa, że wyjechałeś na weekend, a rolety zostały otwarte. Sam ich nie zamknie — wysyła Ci wiadomość: ',
},
{ t: '„Nie zamknąłeś rolet. Zamknąć teraz?"', em: 'quote' },
{
t: ' Odpisujesz „tak" — i dopiero wtedy system zleca to istniejącej automatyce domowej. Decyzja zawsze należy do Ciebie; wykonanie bierze na siebie system.',
},
] as Rich,
tailored: [
{ t: 'System roboczy — budowany pod Ciebie.', em: 'strong' },
{ t: ' To, co ten nadzór pilnuje, dopasowujemy do konkretnej potrzeby.' },
] as Rich,
home: {
title: 'Dla domu',
body: [
{
t: 'Masz już zautomatyzowany dom — światła, rolety, bramy, klimatyzację — ale to automatyka, nie inteligencja: robi dokładnie to, co jej każesz, i nic więcej. Dokładamy warstwę, która ',
},
{ t: 'rozumie kontekst', em: 'strong' },
{
t: ': rozpoznaje Twój samochód po tablicy rejestracyjnej i otwiera bramę, zanim dojedziesz do niej. Widzi na kamerach, że nikogo nie ma w domu, i sama wygasza światła na noc. Zauważa, że wyjechałeś, a coś zostało otwarte — i pyta, zanim cokolwiek zrobi.',
},
] as Rich,
},
business: {
title: 'Dla firm',
body: 'Masz bałagan w dokumentach, obieg papierowy, który nikogo nie satysfakcjonuje, i dane rozsiane po cudzych chmurach, nad którymi nie masz pełnej kontroli. Budujemy Ci paperless na Twoich własnych serwerach — z własną domeną i autoryzacją, bez uzależnienia od zewnętrznych dostawców chmury. Indeksujemy dokumenty, zdjęcia i korespondencję tak, żeby dało się to przeszukać po sensie, nie po słowach kluczowych. Interfejs — webowy panel, a jeśli to naprawdę pasuje do Twojej firmy, także chatbot — dobieramy do tego, czego faktycznie potrzebujesz, a nie do tego, co akurat modne.' as Rich,
},
shared:
'Obie ścieżki łączy to samo: cała konfiguracja tego, co ma działać, jest zapisana jako kod w repozytorium — każda zmiana ma historię i da się ją cofnąć — i obie działają pod tym samym nadzorem, który pilnuje, żeby nic nie zawiodło po cichu.' as Rich,
},
underTheHood: {
title: 'Pod maską — dla ciekawych',
bullets: [
{
body: [
{ t: 'Baza wiedzy nie kończy jako martwy indeks. Nad wyszukiwaniem semantycznym powstaje ' },
{ t: 'czytelna, kompilowana wiki utrzymywana przez model językowy', em: 'strong' },
{
t: ' — pliki tekstowe z linkami między pojęciami, które agent czyta i aktualizuje tak jak człowiek utrzymuje kod. Budujemy to na otwartym standardzie (Google OKF), nie na własnym, zamkniętym formacie — żeby wiedza, którą zbudujemy, zawsze zostawała czytelna i przenośna.',
},
],
},
{
body: 'Do zapytań najpierw sięga tańszy model — droższy dopiero wtedy, gdy sprawa naprawdę tego wymaga. W praktyce: streszczenie całego korpusu dokumentów potrafiło kosztować grosze zamiast dni obliczeń.',
},
{
body: 'Nie wszystko musi być online 24 godziny na dobę. Kiedy główna maszyna śpi, zapytania automatycznie przejmuje zapasowy sprzęt — bez przerwy zauważalnej dla użytkownika.',
},
{
body: 'System sam odróżnia „usługa nie działa" od „usługa śpi zgodnie z planem" — co wcześniej było częstym źródłem fałszywych alarmów.',
},
] as Bullet[],
},
why: {
title: 'Dlaczego to, a nie zwykły monitoring czy zwykła automatyka',
bullets: [
{ lead: 'Rozumiemy kontekst, nie tylko wykonujemy polecenia.' },
{ lead: 'Naprawiamy, nie tylko alarmujemy.' },
{
lead: 'Człowiek naprawdę jest w pętli',
body: ' — decyzje zawsze do Ciebie, wykonanie bierze na siebie system.',
},
{ lead: 'Zero czarnej skrzynki.', body: ' Każda decyzja zostawia ślad, który można później przejrzeć.' },
{
lead: 'Twoje dane zostają Twoje',
body: ' — własny serwer, własna domena, bez uzależnienia od cudzej chmury.',
},
] as Bullet[],
},
status: {
title: 'Uczciwie o tym, gdzie jesteśmy',
paragraphs: [
'Rdzeń nadzoru prowadzi naszą infrastrukturę na co dzień — samonaprawa działa od początku do końca, alerty trafiają na telefon, baza wiedzy odpowiada na pytania nawet gdy główny sprzęt śpi.',
'Dedykowane wdrożenia — pod konkretny dom czy firmę — budujemy w miarę potrzeb, opierając się na tym samym, sprawdzonym rdzeniu. Wolimy powiedzieć wprost, co jeszcze dopracowujemy, niż obiecywać więcej niż działa.',
] as Rich[],
},
cta: {
title: 'Umów rozmowę',
body: 'Powiedz, co chcesz zautomatyzować albo uporządkować — zobaczymy, jak to zbudować i objąć nadzorem, który sami na sobie testujemy.' as Rich,
button: 'Porozmawiajmy',
},
},
};

17
src/i18n/types.ts Normal file
View file

@ -0,0 +1,17 @@
/**
* Shapes for copy that carries inline emphasis. Text with <strong>/<em> inside a
* sentence cannot be one flat string without either splitting the component or
* injecting HTML so it is stored as a list of runs and rendered by <RichText>.
*/
export type Run = {
t: string;
/** 'quote' is an <em> that brightens to full foreground — used for quoted speech. */
em?: 'strong' | 'em' | 'quote';
};
/** Plain text, or a run list when the sentence needs inline emphasis. */
export type Rich = string | Run[];
/** List item rendered as an optional bold lead-in followed by the rest. */
export type Bullet = { lead?: string; body?: Rich };