
Szybkie (w dwa dni robocze) przygotowanie prototypu / makiety / MVP aplikacji
MVP - Minimum Viable Product - najprostsza, funkcjonalna wersja aplikacji, która zawiera jedynie podstawowe funkcje pozwalające rozwiązać kluczowy problem użytkowników. Pojęcie popularne w świecie SaaS, ale ma też zastosowanie przy podejściu do tworzenia aplikacji z szybkim prototypowaniem.
Z doświadczenia wiem, że nawet po wielu godzinach spotkań z przyszłym użytkownikiem aplikacji, przygotowywania koncepcji i architektury rozwiązania, kluczowe pomysły i najwięcej uwag do produktu pojawia się po oddaniu aplikacji do testów, a nawet częściej po oddaniu aplikacji do użytku.
Dzisiaj mamy do dyspozycji narzędzia i technologie, które pozwalają, w bardzo krótkim czasie, przygotować makietę aplikacji, w której użytkownik może wykonywać lub symulować rzeczywiste operacje biznesowe, zgodne z założeniami procesu, który ta aplikacja ma obsługiwać i wspierać. W ten sposób użytkownik bierze czynny udział w procesie tworzenia, a wszystkie zgłaszane rozwiązania lub modyfikację mogę zostać sprawnie zaimplementowane i oddane do kolejnych testów.
Jeśli pracujemy dla nowego, zewnętrznego klienta, który jeszcze nie do końca nam ufa i nie chce ponosić dużych kosztów na początku współpracy, możemy szybko zdefiniować główne założenia projektowe, równie szybko przygotować prototyp i bez ingerencji w jego infrastrukturę, udostępnić prototyp na własnej platformie (jeśli takową dysponujemy) lub skorzystać z jednej z wielu publicznie dostępnych platform hostingowych. W przypadku platform Internetowych, makietę aplikacji błyskawicznie wypełniamy fikcyjnymi i sztucznie wygenerowanymi danymi, nie narażając klienta na wyciek poufnych danych biznesowych.
Na potrzeby tego artykułu poświęciłem dwa dni robocze, żeby przygotować pokazowy prototyp aplikacji, która z założenia może pracować w rejestracji lub sekretariacie placówki medycznej. W tak krótkim czasie udało się wdrożyć funkcje takie jak:
Do końca roku aplikacja pokazowa jest dostępna pod adresem: https://proto-app-001.vercel.app
Zachęcam do utworzenia konta i sprawdzenia jak wyglądają i działają aplikacje tworzone w technologiach, których ostatnio najczęściej używam.
Na końcu tego artykułu udostępniam materiał wideo, na którym demonstruję co potrafi prototyp.
Takie możliwości dają oczywiście duże modele językowe, z których, coraz sprawniej, korzystają agenci / asystenci AI dedykowani do wykonywania prac programistycznych. Osobiście używam GitHub Copilot Pro zintegrowanego z VS Code.
Stosując tradycyjne techniki programistyczne, nie jestem w stanie dostarczyć prototypu w tak krótkim czasie. Mogę zaryzykować stwierdzenie, że tak samo trudno byłoby uzyskać podobny efekt stosują platformę typu low-code, w której, co prawda, buduje się szybko podstawowe funkcjonalności z gotowych klocków, ale przy implementacji bardziej skomplikowanej logiki biznesowej, na drodze stają ograniczenia lub specyfika platformy.
Z pomocą przychodzą też coraz bardziej popularne protokół i serwery MCP, które dają agentowi AI dostęp, na przykład do:
W tym projekcie korzystałem z trzech serwerów MCP:
Konfiguracja w VS Code jest prosta i wymaga przygotowania pliku mcp.json w folderze .vscode:
{
"servers": {
"NUXT UI": {
"type": "http",
"url": "https://ui.nuxt.com/mcp"
},
"NUXT": {
"type": "http",
"url": "https://nuxt.com/mcp"
},
"SUPABASE": {
"type": "http",
"url": "https://mcp.supabase.com/mcp?project_ref=klnuspxlvrxjhudrxcro"
}
}
}
Jeśli chodzi o platformę Supabase, to rzeczywiście tak - utworzyłem nowy, pusty projekt. Wszystkie obiekty DB, takie jak: tabele, polityki RLS, funkcje, triggery, funkcje typu edge, tworzyłem wydając agentowi polecenia w języku naturalnym. To samo jeśli chodzi o wypełnianie tabel fikcyjnymi danymi.
Jeśli chodzi o frontend web-owy, to na start użyłem własnego szablonu, który jest minimalnym szkieletem interfejsu użytkownika i zawiera tylko górną belkę, lewy panel menu (pusty), główną przestrzeń roboczą (pustą), okno logowania i rejestracji użytkownika oraz podstawową integrację z platformą Supabase.
Głównie na wymyślaniu architektury, definiowaniu zadań dla mojego agenta oraz weryfikowaniu i testowaniu wyników jego pracy.
Wszystkie polecenia dla agenta zapisywałem w notatkach i uzbierało się tego około 100 zadań, co przy dwóch dniach (960 minut) intensywnych prac, daje średnio ponad 9,5 minuty na jedno zadania. Zdecydowana większość promptów była jednozdaniowymi, precyzyjnymi poleceniami, których napisanie zajmowało mniej niż 1 minutę, wykonanie agenta to 2-3 minuty, reszta to była moja weryfikacja i szybkie testy. Zdarzały się też bardziej rozbudowane polecenia, które, na przykład, definiowały skomplikowaną logikę i nie miało sensu dzielić ich na mniejsze porcje, co dawało asystentowi lepsze trzymanie kontekstu. Tak na marginesie, agent sam dzielił większe zadanie na mniejsze podzadania oraz ustalał prawidłową kolejność ich realizacji.
Poniżej kilka ciekawszych zadań / promptów, zarówno tych dla bazy danych Supabase oraz frontend-u Nuxt / Nuxt UI.
Potrzebuję w bazie danych nowej tabeli:
- nazwa tabeli: lekarze
- pola: id, imie (text, not null), nazwisko (text, not null)
- włącz politykę RLS: SELECT, INSERT, UPDATE dla zalogowanych użytkowników
Potrzebuję w bazie danych nowej tabeli:
- nazwa: specjalizacje
- pola: id, specjalizacja (text, not null), is_active (boolean, domyślnie true)
- włącz politykę RLS: tylko SELECT dla zalogowanych użytkowników
- wypełnij tabelę 30 specjalizacjami lekarskimi
Do tabeli lekarze dodaj pole id_specjalizacji jako klucz obcy do tabeli specjalizacje.
Dodaj 100 lekarzy do tabeli lekarze z różnych specjalizacji.
Strona /specjalizacje:
- w kolumnie Status wartość prezentuje komponent UBadge
- zostaw go, ale zrób z niego link, którym można zmienić (toogle) wartość w polu is_active tabeli specjalizacje
- obsługa zmiany wartości, komunikaty podobnie jak na stronie /lekarze
- dodaj możliwość sortowania po kolumnie Status
Nowa strona /lekarze/:id:
- dodaj stronę
- w tabeli lekarzy na stronie /lekarze jest kolumna ID - zrób z niej link do nowej strony
- na stronie formularz read-only z danymi lekarza
- poniżej formularza, tabela zdarzeń związanych z lekarzem
- tabela zdarzeń w prostej formie, sortowanie po dacie malejąco, bez możliwości sortowanie i filtrowania
Nie działają linki do nowej strony. Może trzeba plik lekarze.vue zmienić na index.vue w folderze lekarze?
Zmień układ formularza tak aby pola pojawiały się na przemiennie w dwóch kolumnach o tej samej szerokości (użyj grid). Pola typu input czy select powinny zajmować całą szerokość kolumny. Wszystkie błędy i sukcesy pokazuj za pomocą toast. Rozbuduj walidację: z listy lekarzy rodzinnych musi być wybrana pozycja. Lista rozwijana lekarza rodzinnego jest bardzo długa. Dodaj możliwość filtrowania po nazwisku.
Nowa tabela w bazie danych:
- nazwa tabeli: dni
- pola: id, dzien (text, not null, unique)
- włącz politykę RLS: tylko SELECT dla zalogowanych użytkowników
- utwórz mechanizm seed dla tabeli, tak żeby wstawiał lub aktualizował następujące rekordy:
- id: 1; dzien: Poniedziałek
- id: 2; dzien: Wtorek
- id: 3; dzien: Środa
- id: 4; dzien: Czwartek
- id: 5; dzien: Piątek
- Mechanizm seed tabeli dni zrób jako funkcja bazy danych podobnie jak funkcja seed_event_types.
Nowa funkcja brzegowa (edge function):
- nazwa: zaplanuj_wizyte
- argumenty: lekarz_id, pacjent_id, dzien
Logika funkcji zaplanuj_wizyte:
- sprawdź, czy wywołanie funkcji jest w kontekście zalogowanego użytkownika, jeśli nie to błąd
- sprawdź, czy istnieje lekarz o lekarz_id, jeśli nie to błąd
- sprawdź, czy istnieje pacjent o pacjent_id, jeśli nie to błąd
- dzień może być dzisiaj lub w przyszłości, jeśli nie to błąd
- na podstawie daty ustal jaki to dzień tygodnia (Poniedziałek to 1)
- sprawdź, czy istnieje taki dzień w tabeli dni, jeśli nie to błąd
- sprawdź, czy lekarz ma ten dzień tygodnia ustaloną dostępność w tabeli dostepnosc_lekarza, jeśli nie to błąd
- odczytaj wszystkie rekordy z tabeli wizyty dla lekarza na tę datę posortowane rosnąco po godzinie
- ustal pierwszą godzinę dostępności lekarza bazując na zdefiniowanej dostępności w dostępnosc_lekarza, biorąc pod uwagę godzinę startową oraz czas potrzebny na pacjenta (pole czas_na_pacjenta); jeśli nie udało się ustalić wolnej godziny (np. z powodu braku miejsc) to błąd
- dodaj rekord do tabeli wizyty, w pole godzina wstaw ustaloną godzinę pierwszej możliwej wizyty
- dodaj rekord do tabeli lekarze_zdarzenia, zdarzenie_id = 5, opis = Pacjent: Nazwisko Imię pacjenta + data i godzina wizyty
- dodaj rekord do tabeli pacjenci_zdarzenia, zdarzenie_id = 5, opis = Pacjent: Nazwisko Imię lekarza + data i godzina wizyty
Logika funkcji zaplanuj_wizyte - rozbudowa:
- sprawdzaj, czy lekarz jest aktywny, jeśli nie to błąd
- dodaj kontrolę, która pozwala na zaplanowanie pacjentowi tylko jednej wizyty w danym dniu
Strona /lekarze/:id - migracja do Pinia Store:
- strona ma wiele elementów, które potrzebują danych z Supabase REST API
- wszystkie dane potrzebne na tej stronie, łącznie z zagnieżdżonymi komponentami, mają korzystać z globalnego Pinia Store reprezentującego dane lekarza
- wszystkie wywołania Supabase REST API mają znaleźć się w akcjach store
- wykonanie akcji takich jak zakończenie wizyty, odwołanie wizyty, usunięcie dostępności, ustalenie dostępności powinny inicjować odświeżenie tabeli historii zdarzeń lekarza
Strona /pacjenci/:id - migracja do Pinia Store:
- podobnie jak dla lekarzy, migruj do Pinia Store obsługę stanu i komunikacji z Supabase REST API
- akcje takie jak zakończenie wizyty, odwołanie wizyty, powinny inicjować odświeżenie tabeli historii zdarzeń pacjenta
Sprawdź komponent UPagination, stronicowanie dalej nie działa.
Nie działa wywołanie okna dialogowego, nie użyto useOverlay.
Okno dialogowe otwiera się, ale nic się nie pokazuje. Sprawdź dokumentację UModal.
Lista rozwijana lekarzy rodzinnych nie pokazuje wartości do wybory.
Nie podoba mi się rozwiązanie z natywnym form. Użyj UForm, który umożliwia integracje ze schematem walidacji zod.
Nagranie demonstrujące co potrafi 2-dniowy prototyp.