1. Kontekst: Twój App — gość w domu ChatGPT
Zanim zaczniesz rysować przyciski i dobierać kroje pisma, warto przyjąć rzeczywistość: użytkownik nie otwiera „Twojej strony”, on siedzi w ChatGPT. ChatGPT ma już swoje:
- schematy kolorystyczne,
- czcionki i rozmiary,
- odstępy i układ elementów.
Twój widget wyświetla się w tym środowisku, najczęściej w iframe. Wynika z tego ważny wniosek: wizualnie App powinien wyglądać jak naturalne przedłużenie interfejsu ChatGPT, a nie jak baner przywieziony z 2008 roku.
Oficjalne wytyczne OpenAI mówią właśnie o tym: nie łamać systemowych kolorów i czcionek, dodawać jedynie umiarkowane akcenty brandowe i trzymać się podstawowej typografii oraz siatki platformy.
W praktyce oznacza to trzy rzeczy.
Po pierwsze, tło, podstawowy kolor tekstu, standardowa typografia — to wszystko powinno dziedziczyć z ChatGPT lub z systemowych zmiennych, a nie być „bo tak widzę”.
Po drugie, jeśli chcesz „swój styl”, niech będzie skoncentrowany w akcentach: główne przyciski, badge, wyróżnione stany. Ale nie tęczowe tło i nie niestandardowy krój Comic Sans — nawet jeśli bardzo kusi.
Po trzecie, tryby inline i fullscreen tego samego App powinny wizualnie należeć do jednego świata: te same kolory CTA, te same promienie i odstępy kart, ta sama typografia. Użytkownik nie powinien mieć wrażenia, że przechodząc z inline do fullscreen trafił do innego produktu.
Dalej rozłożymy to na warstwy: kolory i motywy, typografia, odstępy i siatka, a następnie — jak Tailwind i shadcn/ui pomagają to wszystko złożyć.
Insight
Sandbox ChatGPT nie tylko ogranicza funkcjonalność Twojego widgetu, ale też dodaje mu własne style.
Po pierwsze — to nagłówek HTML
Oryginał ze strony:
<html lang="ru">
W piaskownicy:
<html lang="en-US" data-theme="light" class="light" style="--safe-area-inset-top: 0px; --safe-area-inset-bottom: 0px; --safe-area-inset-left: 0px; --safe-area-inset-right: 0px;">
Po drugie — to natywne style CSS, aby Twój widget bardziej przypominał ChatGPT:
<style>
html,body,#root{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin:0;padding:0}
html,body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Helvetica Neue,Arial,sans-serif!important}
button,input,textarea,select{font-family:inherit}
html{background-color:#fff}
html.dark{background-color:#212121}
html.mobileSkybridge.dark{background-color:#000}
@supports (font: -apple-system-body){html.mobileSkybridge{font:-apple-system-body}}
</style>
Warto o tym pamiętać — będzie mniej niespodzianek.
2. Motywy i kolory: żyjemy w jasnym i ciemnym wszechświecie
Jasny i ciemny motyw
Interfejs ChatGPT już obsługuje jasny i ciemny motyw. Twój widget wyświetla się wewnątrz jednego z nich, a użytkownik może przełączać się między nimi kiedy chce. To znaczy, że każde twardo zahardkodowane białe lub czarne tła to potencjalna mina.
Wyobraź sobie widget, który rysuje białe tło i czarny tekst. W jasnym motywie wygląda znośnie. W ciemnym — jak reflektor prosto w oczy. Odwrotna sytuacja z czarnym tłem w jasnym motywie nie wygląda lepiej. Dlatego oficjalne rekomendacje sugerują, aby nie hardkodować kolorów, tylko opierać się na motywie/zmiennych hosta.
W Apps SDK środowisko zwykle daje Ci API lub zmienne CSS dla bieżącego motywu. W dokumentacji pojawiają się warianty w stylu window.openai.theme i korzystanie ze standardowych zmiennych CSS ChatGPT. Nikt też nie zabrania używać prefers-color-scheme i narzędzi dark: w Tailwind.
Idea jest taka: Twój widget powinien automatycznie dostosowywać do motywu hosta takie rzeczy jak:
- tło kart (nieco jaśniejsze/ciemniejsze od bazowego tła),
- kolor tekstu (wystarczający kontrast),
- obramowania, cienie i stany hover.
Przykład najprostszej otoczki dla motywu z Tailwind:
// components/AppShell.tsx
export function AppShell({ children }: { children: React.ReactNode }) {
return (
<div className="bg-background text-foreground">
{/* bg-background/text-foreground są nadpisywane przez motyw */}
{children}
</div>
);
}
Gdzie bg-background i text-foreground — to nie standardowe klasy Tailwind, lecz aliasy do zmiennych CSS Twojego systemu projektowego (np. z shadcn/ui), które z kolei są powiązane z jasnym/ciemnym motywem ChatGPT.
Kolory systemowe kontra akcenty brandowe
OpenAI mówi dość jasno: nie wolno zmieniać systemowych kolorów ChatGPT. Bazowy tekst, standardowe panele czatu, tło — to wszystko powinno pozostać w ogólnych barwach platformy. Twoje pole do popisu — akcenty wewnątrz widgetu: przyciski CTA (call to action — główne działanie), badge, drobne elementy.
W praktyce GiftGenius oznacza to, że:
- tło karty prezentu jest zbliżone do systemowego,
- tekst ma zwykły kolor, taki jak tekst w czacie,
- firmowy kolor GiftGenius jest użyty dla głównego przycisku „Wybierz prezent” i ewentualnie dla badge’a zniżki.
Można to ująć w tabeli:
| Element | Co robić | Czego unikać |
|---|---|---|
| Tło widgetu | Dziedziczyć z ChatGPT | Ustawiać jaskrawy gradient brandingowy |
| Tekst podstawowy | Dziedziczyć kolor systemowy | Koloryzować/wyblaklać do nieczytelności |
| Główny przycisk CTA | Używać akcentowego koloru marki | Rysować na nim „tęczę” i 5 kolorów |
| Przyciski/linki drugorzędne | Zbliżone do systemowych linków | Robić je tak samo jaskrawe jak CTA |
| Cienie/ramki | Delikatne, minimalistyczne | Grube neonowe obwódki |
Mini-przykład z Tailwind dla koloru głównego:
// styles/globals.css (fragment)
:root {
--gift-accent: 222 84% 56%; /* hsl */
}
.dark {
--gift-accent: 222 84% 64%; /* nieco jaśniejszy dla dark */
}
// components/GiftButton.tsx
export function GiftButton({ children }: { children: React.ReactNode }) {
return (
<button className="rounded-md bg-[hsl(var(--gift-accent))] px-4 py-2 text-sm font-medium text-white hover:opacity-90">
{children}
</button>
);
}
Nie ruszasz tła całego widgetu, ale subtelnie stosujesz swój kolor do głównego przycisku CTA.
Kontrast i WCAG bez fanatyzmu
Nawet jeśli nie szykujesz się do egzaminu z WCAG, jest prosty punkt odniesienia: tekst musi być czytelny. Im mniejsza czcionka, tym wyższy powinien być kontrast. W kursach o dostępności zaleca się trzymać kontrast tekstu względem tła nie niższy niż około 4.5:1 dla tekstu podstawowego. W szczegóły standardów dostępności nie wchodzimy: potrzebny nam jeden praktyczny drogowskaz — wystarczający kontrast tekstu i tła.
W praktyce:
- nie używaj jasnoszarego tekstu na jasnoszarym tle dla „elegancji”;
- unikaj ciemnoszarego tekstu na niemal czarnym tle w ciemnym motywie;
- sprawdzaj choćby na oko: jeśli mrużysz oczy — użytkownikowi też będzie ciężko.
Można się ze sobą umówić: każdy drugorzędny tekst (podpisy, podpowiedzi) nadal jest czytelny, po prostu trochę mniej akcentowy kolorem i rozmiarem, ale nie „prawie niewidzialny”.
3. Typografia: systemowe czcionki, hierarchia i odrobina zdrowego rozsądku
Czcionki systemowe zamiast „własnej” rodziny
Oficjalne wytyczne zachęcają do używania systemowych krojów platformy, jak SF Pro, Roboto i ich odpowiedniki, a nie do podpinania własnego webfontu. Powód to nie tylko wydajność, ale także to, że Twój App ma wyglądać jak rodzimy element interfejsu.
W aplikacji Next.js najprościej sprawić, by wszystko wewnątrz widgetu dziedziczyło bazowy systemowy stos. W Tailwind jest to zwykle już ustawione jako font-sans. Jeśli chcesz być bardziej jednoznaczny:
// app/layout.tsx (fragment)
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body className="font-sans antialiased">
{children}
</body>
</html>
);
}
Nie trzeba podłączać 3 rodzin przez Google Fonts. Dla edukacyjnego GiftGenius surowy systemowy krój będzie wyglądał schludniej niż np. Lobster.
Hierarchia rozmiarów
Wystarczy nam kilka poziomów typografii: nagłówek bloku, podtytuł/kluczowy parametr, tekst główny i podpis.
Dla karty inline w GiftGenius wygodnie uzgodnić takie poziomy:
| Rola | Klasa Tailwind | Przykład |
|---|---|---|
| Nagłówek karty | |
Nazwa prezentu |
| Kluczowy parametr | |
Cena lub kategoria |
| Opis | |
Krótki opis |
| Podpis/drobiazgi | |
Dostawa, sklep |
Mini-komponent karty:
// components/GiftCard.tsx
type GiftCardProps = {
title: string;
price: string;
description: string;
};
export function GiftCard({ title, price, description }: GiftCardProps) {
return (
<div className="rounded-lg border bg-card p-4">
<h3 className="text-base font-semibold">{title}</h3>
<p className="mt-1 text-sm font-medium text-emerald-600">{price}</p>
<p className="mt-2 text-sm text-muted-foreground">{description}</p>
</div>
);
}
Tu:
- nie ma ogromnego H1;
- wszystkie informacje są kompaktowe;
- hierarchia jest czytelna po rozmiarze i grubości kroju.
Wyrównanie i długość wierszy
Interfejs czatu jest zwykle wąski, zwłaszcza w trybie inline. Dlatego nie trzeba przegrzewać głowy złożoną typografią: normalne wyrównanie do lewej i długość wiersza 40–60 znaków są w pełni komfortowe.
Przydatne nawyki:
- nie centrować długich tekstów w karcie — trudniej je się czyta;
- nie pisać WSZYSTKIEGO WIELKIMI LITERAMI;
- nie robić tekstu bazowego mniejszego niż 14 px (w Tailwind to text-sm) bez bardzo poważnego powodu.
W razie wątpliwości pamiętaj: czytać będzie zmęczony człowiek na telefonie w metrze, a nie Ty z idealnym 27‑calowym monitorem.
4. Odstępy, gęstość i siatka
Jeśli kolory i czcionki to „farby”, to odstępy to powietrze. Bez nich nawet najbardziej schludne karty zamieniają się w chaos.
OpenAI w swoich rekomendacjach podkreśla: elementy nie powinny być „sklejone”, odstępy i promienie lepiej brać z systemu projektowego lub UI‑frameworka (Tailwind, shadcn/ui itd.), a przewijanie poziome należy minimalizować.
Zasada „oddychania”
Najprostszy wzorzec: używać jednej skali odstępów (np. krok 4 px lub 8 px) i nie wymyślać za każdym razem „własnego” rozmiaru. W Tailwind jest to już wbudowane: p-2, p-3, p-4, gap-3 itp.
Przykład niewielkiej siatki dla listy prezentów w trybie inline:
// components/GiftListInline.tsx
export function GiftListInline({ children }: { children: React.ReactNode }) {
return (
<div className="flex flex-col gap-3">
{children}
</div>
);
}
Każda karta jest oddzielona gap-3, ma swoje wewnętrzne p-4, i to już wystarczy, by lista nie wyglądała jak „prześcieradło”.
Kolumny: inline kontra fullscreen
W dokumentach UX dla Apps SDK zaleca się w trybie inline trzymać 1–2 kolumn kart, a w fullscreen można pozwolić sobie na 2–3 przy wystarczającej szerokości.
Powód jest prosty: w czacie szerokość jest ograniczona, zwłaszcza na mobile, i dwie kolumny to już granica czytelności. W fullscreen dostajesz prawie cały ekran i możesz ułożyć treść gęściej.
Orientacyjny schemat:
flowchart LR
subgraph Inline
A[1 kolumna
wąski ekran]
B[2 kolumny
na desktopie]
end
subgraph Fullscreen
C[2 kolumny
scenariusz podstawowy]
D[3 kolumny
dla siatek/katalogów]
end
Implementacja w Tailwind dla GiftGenius:
// components/GiftGrid.tsx
export function GiftGrid({ fullscreen, children }: { fullscreen?: boolean; children: React.ReactNode }) {
const base = fullscreen ? "grid-cols-2 md:grid-cols-3" : "grid-cols-1 sm:grid-cols-2";
return (
<div className={`grid gap-4 ${base}`}>
{children}
</div>
);
}
W trybie inline dajesz jedną kolumnę na mobile i dwie na szerszych ekranach. W fullscreen od razu robisz 2–3 kolumny w zależności od szerokości.
Unikamy poziomego przewijania
Czat z natury jest pionowy. Użytkownik jest przyzwyczajony do przewijania w dół, a nie w bok. Dlatego:
- staraj się, aby tabele i karty mieściły się w szerokości kontenera;
- nie ustawiaj sztywnych szerokości typu width: 600px; dla elementu żyjącego w elastycznym kontenerze;
- używaj max-w-full, overflow-x-auto tylko jako „ostatniej deski ratunku”, a nie domyślnie.
Dla kart GiftGenius wygodnie ustawić w-full i pozwolić siatce zdecydować, ile zmieści się w rzędzie.
5. Responsywność wewnątrz kontenera ChatGPT
W zwykłym frontendzie masz pełną kontrolę nad viewportem. W ChatGPT kontrola jest ograniczona: Twój widget jest umieszczony w kontenerze czatu, który ma własne rozmiary i reguły. Apps SDK daje kilka przydatnych mostków: maksymalną wysokość, safe area dla wcięć ekranu, typ urządzenia itd.
maxHeight i ograniczenia pionowe
W trybie inline ChatGPT może ograniczać wysokość widgetu, aby nie „zjadał” całego ekranu. Hooki takie jak useMaxHeight() pozwalają sprawdzić, ile miejsca można teraz uczciwie zająć, i powiesić wewnętrzne przewijanie tam, gdzie trzeba.
Pseudokod:
// Pseudokod, nie prawdziwe API:
const maxHeight = useMaxHeight();
return (
<div style={{ maxHeight, overflowY: "auto" }}>
<GiftGrid>{/* ... */}</GiftGrid>
</div>
);
Dzięki temu unikasz sytuacji, w której widget opiera się o dolną krawędź ekranu, a wiadomości czatu „zjeżdżają” gdzieś w przeszłość.
safeArea i urządzenia mobilne
Na urządzeniach mobilnych u góry i na dole mogą być wcięcia, pasek statusu, panele systemowe. Apps SDK pozwala uzyskać safeArea i dostosować odstępy tak, by nic nie zniknęło pod „notchem” telefonu.
Na poziomie CSS można dodać dodatkowe paddingi:
// Pseudokod
const { top, bottom } = useSafeArea(); // załóżmy, że zwróci { top: 8, bottom: 16 }
return (
<div style={{ paddingTop: top, paddingBottom: bottom }}>
{/* treść */}
</div>
);
W ramach lekcji ważniejsza jest zasada: widget powinien respektować ogranicznik wysokości i bezpieczny obszar, w przeciwnym razie UX natychmiast zamienia się w „przewiń jeszcze trzy razy, żeby zobaczyć przycisk”.
6. Tailwind i shadcn/ui: nie wymyślać przycisków na nowo
Pisanie całego UI ręcznie w czystym CSS to dziś niemal sport ekstremalny. W kontekście ChatGPT Apps dużo łatwiej wziąć sprawdzoną bibliotekę i dostroić ją do wymagań platformy. W kursie opieramy się na Tailwind i shadcn/ui jako bazowym stosie.
Tailwind jako słownik odstępów i kolorów
Tailwind daje wygodny zestaw narzędzi:
- odstępy (p-4, gap-3),
- rozmiary (text-sm, text-base),
- kolory (text-muted-foreground, bg-card), które w shadcn/ui i podobnych systemach są już powiązane ze zmiennymi CSS motywu.
To idealnie wpisuje się w wymagania ChatGPT:
- nie wymyślasz arbitralnych odstępów,
- konsekwentnie ustawiasz rozmiary tekstu,
- nie psujesz kolorów systemowych, lecz używasz uprzednio uzgodnionych tokenów.
shadcn/ui jako zestaw schludnych komponentów
shadcn/ui (i podobne biblioteki) dostarczają gotowe Card, Button, Input, Tabs itp., dostrojone do motywu Tailwind. To znacząco przyspiesza składanie schludnego, minimalistycznego interfejsu, szczególnie dla kart GiftGenius.
Przykład GiftCard z użyciem shadcn/ui:
// components/GiftCardShadcn.tsx
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
type GiftCardProps = {
title: string;
price: string;
description: string;
};
export function GiftCardShadcn(props: GiftCardProps) {
return (
<Card>
<CardHeader>
<CardTitle className="text-base">{props.title}</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
<p className="text-sm font-medium text-emerald-600">{props.price}</p>
<p className="text-sm text-muted-foreground">{props.description}</p>
<Button className="mt-2">Wybierz prezent</Button>
</CardContent>
</Card>
);
}
Najważniejsze nie jest samo shadcn, lecz zasady:
- nagłówek nie jest gigantyczny;
- opis jest czytelny;
- przycisk jest wystylizowany według wspólnego systemu projektowego, a nie „po swojemu”.
Dostrojenie do ChatGPT
W realnym projekcie możesz dostroić paletę do minimalistycznego stylu ChatGPT: jasne tło, miękkie cienie, schludne promienie. Plan modułu wprost sugeruje opierać się na istniejącym systemie projektowym, a nie tworzyć własny wszechświat.
Proste podejście:
- wziąć bazę shadcn/ui;
- zostawić systemowy krój pisma;
- ustawić jeden–dwa kolory brandowe w tokenach primary / accent;
- upewnić się, że zarówno inline, jak i fullscreen używają tych samych tokenów.
Dzięki temu otrzymujesz spójne wizualne jądro bez zbędnego wysiłku.
7. Język wizualny GiftGenius: zbieramy wszystko w całość
Usystematyzujmy, co w naszym przykładowym GiftGenius można już uznać za „język wizualny”.
Po pierwsze, schemat kolorów. Tło i tekst dziedziczą z ChatGPT; kolor akcentowy — nierzucający się w oczy, ale zauważalny — stosowany do przycisków CTA i ewentualnie badge’y zniżek. W ciemnym motywie ten akcent jest nieco jaśniejszy, aby zachować kontrast.
Po drugie, typografia. Bazowy systemowy krój, rozmiary text-sm dla tekstu podstawowego i text-base dla nagłówków kart. Kursywa i kapitaliki używane rzadko, tylko gdy naprawdę trzeba. Nagłówki w fullscreen‑kreatorze o krok wyżej, ale nadal bez krzyczącego text-4xl.
Po trzecie, odstępy i siatka. W trybie inline lista prezentów — jedna lub dwie kolumny z gap-3/gap-4, każda karta z p-4. W trybie fullscreen — 2–3 kolumny, kroki kreatora z wystarczającymi przerwami między formularzami i przyciskami. Bez poziomego przewijania w głównych scenariuszach.
Niewielki schemat dla ekranów GiftGenius:
graph TD A[Inline: lista prezentów] --> B[GiftCard
kolory/typografia/CTA] A --> C[GiftGrid 1-2 kolumny] D[Fullscreen: kreator doboru] --> E[Krok 1
formularz] D --> F[Krok 2
filtry/zakresy] D --> G[Krok 3
potwierdzenie] B --> H[GiftButton
akcent marki]
Po czwarte, kompatybilność z kontekstem hosta. Wszystkie elementy zachowują się poprawnie przy przełączaniu jasnego/ciemnego motywu, respektują maxHeight i nie chowają się pod safe‑area. Kolory nie kłócą się z ChatGPT, a przyciski CTA wszędzie wyglądają tak samo, aby użytkownik na poziomie pamięci mięśniowej wiedział, gdzie kliknąć.
Taki zestaw decyzji sprawia, że Twoja aplikacja nadaje się do demonstracji nie tylko programistom, ale i prawdziwym użytkownikom czy product managerom: będzie o czym rozmawiać poza „tu mamy MCP, a tu Agents SDK”.
8. Dostępność (Accessibility Guidelines, WCAG AA)
Wspomnieliśmy już WCAG, gdy mówiliśmy o kontraście tekstu i tła w sekcji 2.3. Interesował nas tam jeden praktyczny drogowskaz — nie zabijać czytelności. Teraz spojrzymy na dostępność nieco szerzej: jak ten sam interfejs wygląda dla tych, którzy nie widzą go oczami, oraz dla samego ChatGPT w trybie głosowym.
WCAG AA — to poziom standardu dostępności z międzynarodowego zestawu zasad WCAG (Web Content Accessibility Guidelines), które opisują, jak tworzyć strony i interfejsy dostępne dla ludzi z różnymi ograniczeniami wzroku, motoryki, funkcji poznawczych itd.
Główna idea WCAG AA — przekształcić interfejs z „teoretycznie dostępnego” w naprawdę użyteczny. Ten poziom zawiera dziesiątki wymagań, które bezpośrednio wpływają na jakość interakcji. Wśród nich — wspomniany próg kontrastu tekstu i tła około 4.5:1, a także wymagania dotyczące rozmiarów obszarów klikalnych, stanów fokusu, błędów w formularzach itd.
Oddzielna warstwa to wsparcie technologii asystujących, w tym czytników ekranu. Poziom AA wymaga poprawnej semantyki: nagłówki mają być nagłówkami, listy — listami, przyciski — przyciskami, a elementy interaktywne powinny mieć właściwie przypisane role i alternatywy tekstowe. Pozwala to użytkownikom korzystającym z VoiceOver, TalkBack czy NVDA w pełni rozumieć strukturę i sens interfejsu.
Screen reader (czytnik ekranu)
Screen reader (czytnik ekranu) — to program, który odczytuje i/lub strukturyzuje zawartość ekranu, umożliwiając osobom z zaburzeniami widzenia korzystanie z komputera, smartfona czy aplikacji webowych.
Ale screen reader to nie tylko „program, który czyta tekst na głos”. To pełnoprawny system interakcji z interfejsem, który zamienia wizualną prezentację strony lub aplikacji w dostępną percepcyjnie dźwiękową i ustrukturyzowaną nawigację.
ChatGPT, screen reader i WCAG AA
Jeśli Twój widget jest oznaczony zgodnie z zasadami WCAG AA (poprawne role, nagłówki, etykiety przycisków), staje się zrozumiały nie tylko dla czytników ekranu, lecz także dla ChatGPT w trybie głosowym. Użytkownik mówi do ChatGPT głosem, a model, opierając się na tej samej strukturze semantycznej, może „wirtualnie” robić to samo co człowiek: znajdować potrzebne elementy interfejsu, naciskać przyciski, przechodzić do linków itp.
Zgodnie z wymaganiami ChatGPT Store wsparcie standardu WCAG AA jest obowiązkowe dla każdej aplikacji. Każdy widget i każde narzędzie powinny mieć maksymalnie jakościowe i szczegółowe opisy, a layout — być wykonany zgodnie ze standardami WCAG AA: poprawna semantyka, czytelne etykiety, przewidywalne stany.
Dlatego wymaganie WCAG AA to nie osobna „funkcja dla osób ze specjalnymi potrzebami”, lecz bazowa zasada projektowa po to, by ChatGPT Apps mogła w pełni współpracować z Twoją aplikacją, również wtedy, gdy użytkownik rozmawia z nią w trybie głosowym.
Do scenariuszy voice‑UX, różnic dialogu głosowego względem tekstowego i wymagań ChatGPT Store jeszcze wrócimy — w innych lekcjach tego modułu i w module o publikacji App. Ale wszystko to stoi na fundamencie, który właśnie zobaczyłeś: tryb głosowy = multimodalność + dostępność (WCAG AA + czytniki ekranu).
9. Typowe błędy wizualnego designu ChatGPT App
Błąd nr 1: Twardo zahardkodowane białe/czarne tło i kolory tekstu.
Deweloper rysuje białe tło i czarny tekst, nie myśląc o ciemnym motywie. W jasnym jeszcze jakoś działa, w ciemnym — zamienia się w reflektor i psuje cały UX. Lepiej używać kolorów systemowych i motywu hosta (zmienne CSS, prefers-color-scheme lub API Apps SDK), a własne kolory trzymać tylko dla akcentów.
Błąd nr 2: Zbyt agresywny branding.
Pojawia się jaskrawe gradientowe tło, niestandardowy krój, pstrokate ramki. Widget zaczyna wyglądać jak baner promocyjny, a nie część interfejsu ChatGPT. Wytyczne mówią odwrotnie: minimalistyczny, „rodzimy” wygląd, z subtelnym użyciem koloru marki tylko w kluczowych elementach, np. w głównych przyciskach.
Błąd nr 3: Brak hierarchii w typografii.
Wszystkie teksty w jednym rozmiarze i wadze albo przeciwnie — trzy poziomy nagłówków na małej karcie, do tego kapitaliki. Użytkownik nie wie, co jest najważniejsze: nazwa, cena czy opis. Lepiej z góry uzgodnić 3–4 poziomy i wszędzie się ich trzymać: nagłówek, kluczowy parametr, tekst główny, podpis.
Błąd nr 4: Sklejone elementy bez odstępów.
Karty stykają się ze sobą, tekst przy krawędzi, przyciski przyklejone do tekstu. Na desktopie jeszcze ujdzie, na mobile zamienia się w szum wizualny. Zaleca się używać jednej skali odstępów (np. klasy Tailwind p-4, gap-3) i nie oszczędzać na powietrzu.
Błąd nr 5: Próba wciśnięcia 4–5 kolumn w trybie inline.
Deweloper mentalnie nadal jest na stronie sklepu i robi w czacie siatkę z czterech wąskich kart. Na szerokim ekranie wygląda to dyskusyjnie, na mobile — w ogóle nieczytelnie, dochodzi poziome przewijanie. W inline zwykle wystarczy jedna–dwie kolumny; trzecią zostaw trybowi fullscreen.
Błąd nr 6: Ignorowanie ograniczeń wysokości i safe‑area.
Widget rysuje gigantyczną listę bez wewnętrznego scrolla i bez uwzględnienia maxHeight, przez co przyciski lądują „poniżej dna ekranu”. Albo elementy chowają się pod wcięcie ekranu na mobile. Warto używać danych o maksymalnej wysokości i bezpiecznym obszarze, by poprawnie rozdzielać wysokość i odstępy w środku.
Błąd nr 7: Niespójny wygląd przycisków i kart między inline a fullscreen.
W trybie inline przycisk jest zielony i zaokrąglony, a w fullscreen — niebieski i kwadratowy. Użytkownik traci poczucie jednego produktu. Trzeba wynieść bazowe style przycisków i kart do wspólnego komponentu/motywu i używać ich we wszystkich trybach.
Błąd nr 8: „Autorski” krój i dekoracyjne fajerwerki.
Podłączenie ciężkiego webfontu „żeby było ładnie” łamie wizualną spójność z ChatGPT, a czasem psuje wydajność. Wytyczne platformy mówią, by używać systemowych krojów i schludnej typografii. Jeśli bardzo chcesz się wyrazić jako projektant — lepiej popracuj nad ikonami i microcopy, a nie rób rewolucji fontowej.
GO TO FULL VERSION