Programmierung

Nov 9, 2020

Mit Next.js und Hasura in kürzester Zeit einsatzbereit

Mit Next.js und Hasura in kürzester Zeit einsatzbereit

Mit Next.js und Hasura in kürzester Zeit einsatzbereit

Adrian Pilarczyk

Senior Backend-Entwickler

Gelbe Blume
Gelbe Blume
Gelbe Blume

JamStack boomt mit Tools wie Next.js und Hasura. Du denkst, nur weil du React kennst, heißt das, dass du für den Rest deines Lebens To-Do-Listen erstellen wirst? Ich habe einige Neuigkeiten für Sie.



{

Um nicht aus dem gängigsten Webentwicklungsklischee auszubrechen, Tiere als Gegenstand eines lustigen Nebenprojekts zu verwenden, werden wir eine einfache Hundeheim-Website erstellen. Sie wird vorerst aus drei Routen bestehen: der Startseite, der allgemeinen /Hunde-Ansicht und der Detailansicht eines einzelnen Hundes. In diesem Blog-Post werden wir API-mäßig nur die Daten mit einer GraphQL-Abfrage auslesen - keine Mutationen oder Abonnements (noch).

Das allgemeine Ziel ist es, eine ordentliche Grundlage für eine SSR-React-Anwendung zu präsentieren, die Sie später für einige größere Projekte verwenden können. Wir werden Next.js + TypeScript als UI-Framework verwenden und unsere Daten werden in einem Service namens Hasura gespeichert, von dem wir sie über eine automatisch generierte GraphQL-API abrufen werden.

Ich werde nicht zu viel Zeit darauf verwenden, irgendetwas Auffälliges zu tun, zumindest nicht am Anfang dieser Serie, wenn Sie also hier sind, um Ihre Augen zu erfreuen, kann ich Ihnen wohl nur empfehlen, zum Ende dieser Seite zu scrollen und sich dort mit einem hübschen Kerl zu treffen. Die Richtung dieser Initiative ist jedoch ganz Ihnen überlassen - wenn Sie das Gefühl haben, dass ich damit irgendwohin gehen soll, lassen Sie es mich einfach auf Twitter wissen: @pilarenko.

Sie können von mir erwarten, dass ich Sie nicht im Regen stehen lasse, mehrere Schritte im Prozess überspringe und davon ausgehe, dass Sie alles wissen, aber ich muss Sie warnen die elementaren React-, TypeScript- und GraphQL-Kenntnisse sind ratsam. Ich werde mein Bestes tun, um die Best Practices bei der Verwendung dieser Tools zu befolgen, aber Sie können gerne einen Pull Request erstellen, wenn etwas zusätzliche Arbeit benötigt. The repository is available here.

Agenda

  1. Set up Next.js + TypeScript Anwendung

    1. Basic setup (kann mit npx create-next- übersprungen werden)app)

    2. Adding TypeScript

    3. Adding routes

  2. Set up Hasura backend

  3. Next.js + Hasura

    1. Environment variables

    2. From server to client

    3. Apollo configuration

    4. useFetch

    5. Daten auf der Server-side

  4. Deploy

Useful links

1. Next.js + TypeScript Anwendung einrichten

1.1 Grundlegende Einrichtung

Ich habe mich entschieden, das gesamte Projekt von Grund auf neu zu starten, weil 1) ich denke, dass es lehrreich sein könnte 2) die App so einfach ist, dass es nicht notwendig ist, eine Vorlage aus dem offiziellen Next.js-Repository zu schnappen, nur um im ersten Schritt die Hälfte des Boilerplates zu pflügen. Also nehmen wir das gute alte:

Sie können "das CLI eingeben", da die Fragen, die das CLI stellt, für unser Projekt nicht super relevant sind. Am Ende haben wir einen package.json, der dringend seine ersten Abhängigkeiten braucht. Bringen wir sie:

Lassen Sie' uns auch einen erstellen.gitignore-Datei und fügen dort unseren klobigen Boi node_modules ein.

Dann müssen wir package bearbeiten.json, um Next-Skripte hinzuzufügen, die für die Ausführung des Projekts oder die Erstellung benötigt werden.

Die Struktur der Next.js Anwendung dreht sich um die Verwendung des Verzeichnisses pages für die Definition der Routen. Das bedeutet, dass jede .jsx/.tsx-Datei, unabhängig davon, wie tief sie in ihren eigenen Unterordnern verschachtelt ist, einer Unterroute entspricht. Fürs Erste erstellen wir die Homepage ("/"), die Next.js als pages/index.jsx erwartet.

Und lassen Sie'uns das mit etwas grundlegendem React auffüllen:

Hatte ich Ihnen nicht gesagt, dass es TypeScript geben würde? Keine Sorge, ich erinnere mich. Lassen Sie uns nur schnell überprüfen, ob alles wie erwartet funktioniert und wir werden es in .tsx konvertieren. Run:

and hopefully witness this beauty:

Aber das'ist nicht das einzige, was Sie sehen werden - Ihr Auge wird wahrscheinlich das Erscheinen von sehen.next folder.

Was sich darin befindet, sind alle Dev-Build-Dateien, die Next.js für uns generiert, um bequem mit der Anwendung lokal zu arbeiten. Schauen Sie nicht hinein, es ist in Elbisch geschrieben. Das Beste, was Sie tun können, ist .next zu .gitignore hinzuzufügen.

1.2 Hinzufügen von TypeScript

Nun, lasst uns endlich zu TypeScript kommen und die süße Next.js Magie nutzen. Geben Sie:

ein, um eine Datei zu erstellen, die zur Angabe von Compiler-Optionen für TypeScript verwendet wird. Von diesem Moment an wird Next.js Sie durch den Rest führen. Zunächst müssen Sie sich nicht einmal um das Ausfüllen der Konfiguration kümmern, denn sobald Sie npm run dev erneut starten, wird sie automatisch erzeugt. Wenn Sie das nächste Mal einen Blick darauf werfen, werden Sie etwas ähnliches wie das hier sehen:

Dann überprüfen Sie die Konsole auf die Liste der Pakete, die zur Fertigstellung des Setups erforderlich sind. Höchstwahrscheinlich werden es die folgenden sein:

Das erste ist der Star selbst, gefolgt von Typdefinitionen für React und Node, die wir in unserer Entwicklungsumgebung nutzen können.

Schön, oder? Nachdem wir tsconfig abgedeckt haben, ist es ' endlich an der Zeit, den Abzug für die Änderung der Erweiterung zu betätigen, also lassen Sie uns index.jsx to index.tsx.

Die Änderung der Erweiterung bringt an sich nichts, aber ich schlage vor, dass wir unsere schöne Liebesgeschichte zwischen React und TypeScript beginnen, indem wir den Typ von React Functional Component (React: FC) to our Index function. Sie tut'noch nichts, aber das'ist normalerweise die Geschichte mit TypeScript - sie'ist nutzlos, bis sie es nicht ist.

1.3 Hinzufügen von Routen

Nun, da wir unsere Indexseite haben, fügen wir die restlichen Unterrouten hinzu, beginnend mit /dogs.

Die Art und Weise, wie ich mir die Anwendung vorstelle, ist, den Benutzer auf die hundespezifische Detailseite umzuleiten, nachdem er auf das Miniaturfoto des Hundes auf der /dogs Seite geklickt hat. Dazu benötigen wir die besagte Hundedetailseite, die an der ID des Hundes' erkannt wird. Wir erwarten, dass die URL etwa so aussieht: www.dog-shelter.com/dog/f1297fb9-1097-45be-a0a3-6ca63f5a8ed9, wobei nach dem Teil "/dog/" die uuid steht, die dynamisch ist - sie ist für jeden Hund anders. Wir können das in Next.js-Routen durch die Klammer-Syntax übersetzen, wobei wir den dynamischen Parameter in einer [Klammer] halten. Der Pfad für unsere einzelne Hundekomponente sollte also wie folgt aussehen:

Temporarily, alles, was wir tun werden, ist die "Hund's" id aus der URL mit Hilfe von useRouter zu lesen und sie innerhalb der Komponente anzuzeigen. It can look like this:

So sollte unser aktueller Ordner seiten dieser Struktur folgen:

Nun haben wir eine einfache Next.js-Anwendung mit drei Routen und einer nicht existierenden Benutzeroberfläche. Yaay. Zeit, es ein bisschen aufregender zu machen.

2. Hasura

Nichts bringt den Geist von JamStack besser zum Ausdruck als Hasura. Ich empfehle Ihnen, sich anzuschnallen, denn dank dieses Dienstes werden wir in wenigen Minuten ein vollständiges Backend mit GraphQL API erstellen.

Hasura tut Wunder, indem es Ihnen so wenig wie möglich von einer Datenbank, API und sogar etwas Backend-Logik verrät, obwohl es sicherlich einige Türen offen hält, wenn Sie daran interessiert sind, herumzuschnüffeln. Wir werden es für den Moment einfach halten, also lasst' uns einfach auf den Punkt kommen.

Please visit https://cloud.hasura.io/ und loggen Sie sich mit dem Dienst Ihrer Wahl ein, dann entscheiden Sie sich für "Testen Sie eine kostenlose Datenbank mit Heroku". Heroku mag im JamStack-Universum ein wenig in Vergessenheit geraten sein, aber hier erfüllt es definitiv seinen Zweck. Sie müssen allerdings ein Konto erstellen (falls Sie noch keins haben).

Ganz am Ende des Prozesses klicken Sie auf "Projekt erstellen" und Sie sollten endlich im Hasura Dashboard landen.

Nachdem der Dienst erfolgreich initialisiert wurde, fahren Sie fort und gehen Sie direkt zur Seite "Data", wo wir uns endlich die Hände schmutzig machen können. Klicken Sie auf "Tabelle hinzufügen", wo wir einige Spalten zu unserer Tabelle und damit, dank Hasura und GraphQL-Magie, zu unserer API hinzufügen können. Dies kann sich ein wenig überwältigend anfühlen, wenn Sie noch nie mit einer Datenbank gearbeitet haben, aber keine Sorge, Hasura wird es so einfach wie möglich machen.

Lassen Sie' uns damit beginnen, unserer Tabelle einen Namen zu geben (in meinem Fall: "Hunde") und eine Reihe von Feldern hinzufügen. Beachten Sie, dass Hasura UI eine intelligente Autovervollständigung bietet, die darauf basiert, welche Art von Datenbankfeld Sie gewählt haben (z.B. now() für den Zeitstempel).

Ich schlage vor, den Abschnitt "Häufig verwendete Spalten" zu verwenden und id mit der UUID-Voreinstellung zu nehmen, created_at und updated_at, wobei Sie damit nach Belieben herumspielen können. Der Rest der Felder ist Ihnen überlassen, aber ich werde mich an mein "Hunde"-Thema halten und name hinzufügen, age, bio and image. Machen Sie sich nicht zu viele Gedanken darüber, denn Sie können es später noch ändern.

Stellen Sie nur sicher, dass Sie "id" als Primärschlüssel Ihrer Tabelle wählen.

Dann gehen Sie zu unserer neu erstellten Tabelle und klicken auf die Registerkarte "Zeile einfügen", um sie mit einem ersten Datensatz zu füllen. Wenn Sie Felder mit vorgegebenen Standardwerten haben, werden diese von Anfang an verwendet, so dass ich mich in meinem Fall nur um "Name", "Alter", "Bild" und "Bio" kümmern muss.

Done! Und ich meine wirklich erledigt - das Einzige, was Sie jetzt auf der Hasura'-Seite tun können, ist mit der GraphiQL-Schnittstelle herumzuspielen, um Ihre API abzufragen.

{

Mit zunehmender Erfahrung mit GraphQL-APIs werden Sie mehr und mehr mit dieser Ansicht vertraut werden: lernen Sie GraphiQL kennen. Dies ist Ihr interaktiver GraphQL-Spielplatz, von dem aus Sie auch ohne umfangreiche Kenntnisse der Sprache eine GraphQL-Abfrage erstellen können. Sie sollten in der Lage sein, auf Ihre Tabelle von der Seite "Explorer" aus zuzugreifen, genau dort, wo ich meine "Hunde" habe. Durch Anklicken der Kontrollkästchen können Sie der Abfrage automatisch ein Feld hinzufügen, ganz im Sinne des GraphQL-Credos: Man holt nur, was man braucht.

3. Next.js + Hasura

3.1 Umgebungsvariablen

Nun, gehen wir zurück zu unserer Next.js-Anwendung.

Um in Zukunft nicht damit belästigt zu werden, fügen wir zunächst die Hasura-Endpunkt-URL als Umgebungsvariable zu unserem Projekt hinzu. Glücklicherweise hat Next.js in dieser Hinsicht massive Verbesserungen in eine der letzten Versionen, so dass es'so einfach ist wie:

  1. creating .env file

  2. adding it to .gitignore

  3. , in dem wir unsere URL speichern und dabei beachten, dass 1) sie der Namenskonvention "NEXT_PUBLIC_XYZ" folgen muss, so dass es sowohl auf dem Client als auch auf dem Server zugänglich ist. 2) Kopieren Sie nicht die "https://{ENTITY_811}}-Protokoll, da wir mit der URL flexibel sein wollen.

Therefore, our .env should look like this:

3.2 Vom Server zum Client

Next.js glänzt am meisten, wenn man seine Fähigkeiten auf der Seite des Datenabrufs richtig nutzt. Das Framework bietet Ihnen eine Reihe von Methoden, die Sie auf seiten/Routenkomponenten ausführen können, die festlegen, wie dieser Teil der Anwendung aufgebaut und bedient wird. Wenn Sie sich zum Beispiel für getServerSideProps - eine Funktion, die wie ein "Fenster" zum serverseitigen Bereich von Next.js funktioniert - diese gesamte Seite wird automatisch serverseitig gerendert.

Das perfekte Szenario für eine solche Seite wäre, wenn wir während des Builds die Anzahl und den Inhalt aller URLs unter dieser Subroute nicht kennen, da sie ständig hinzugefügt werden können. Denken Sie an eine große E-Commerce-Website, auf der jede Minute neue Produkte und Angebote hinzugefügt/entfernt werden können.

Unser Anwendungsfall ist einfacher - die Anzahl der Hunde im Tierheim wird sich nicht allzu sehr ändern, so dass wir in der Lage sein werden, sie statisch zu rendern. Das bedeutet, dass wir in Zukunft eher mit getInitialProps oder getStaticProps Methode arbeiten werden, aber um zu zeigen, dass sie sich in der Implementierung nicht allzu sehr unterscheiden, fügen wir hier kurz getServerSideProps hinzu.

Notice: console.log doesn't show in the browser, but...

...in the terminal, on the server-side, it does.

So lassen Sie'uns eine fest kodierte "Scooby-Doo" Zeichenkette an unsere UI übergeben.

3.3 Apollo-Konfiguration

Während dieses Muster für reale Anwendungen völlig nutzlos ist, wird die Idee, die Daten von der Server-Seite an den Client zu übergeben, verwendet, sobald wir anfangen, sie von der API zu holen. Und dafür brauchen wir Apollo:

Apollo lässt sich am besten als Brücke zwischen dem UI-Framework (diese Rolle wird in unserem Stack von React/Next.js übernommen) und GraphQL beschreiben. Dieser Koloss von einer Bibliothek bietet eine Vielzahl von Funktionen sowohl für die Erstellung von GraphQL-Servern, als auch für das Abrufen von Daten aus einer bestehenden GraphQL-API.

Es gibt keinen goldenen Standard für das Abrufen von Daten (serverseitig vs. clientseitig), da es in der Praxis meist auf eine Kombination aus beidem hinausläuft. Deshalb möchte ich Ihnen zunächst zeigen, wie wir das im Browser mit Hilfe des useQuery-Hooks machen können. Um dies zu ermöglichen, müssen wir zunächst unseren ApolloClient initialisieren und über die gesamte Anwendung verteilen. Dankenswerterweise hat Next.js genau dafür eine Komponente namens pages/_app.tsx . Sie können es sich als einen Wrapper vorstellen, der jede Seite umhüllt.

Kümmern wir uns zuerst um unseren ApolloClient:

{

Wie wir sehen können, braucht es nicht viel, um zu funktionieren: nur die URL unserer Hasura Cloud GraphQL API (gespeichert in einer env var) und eine neue Instanz von InMemoryCache(), die das Caching der Anfragen für uns übernimmt. Dann können wir es unseren Routen wie folgt zur Verfügung stellen:

3.4 useFetch

And dann auf unsere Seiten/Hunde, wobei wir, wie im ursprünglichen Plan angenommen, alle Hunde abrufen und einige grundlegende Informationen über sie anzeigen wollen. Hier kommt uns die GraphiQL-Spielwiese zu Hilfe - wir können unsere Abfrage dort spezifizieren und sie einfach in unseren Editor kopieren, sobald sie fertig ist. Um sie für Apollo lesbar zu machen, müssen wir sie allerdings mit einer gql Funktion verpacken:

Dann bringen wir den bereits angekündigten Hook namens useQuery ein. Ausgestattet mit der GraphQL-Serverkonfiguration ist es dank der Arbeit, die wir in der _app.tsx geleistet haben, nun in der Lage, ohne viele weitere Parameter zu arbeiten. Das einzige, was wir ihm übergeben müssen, ist unsere Anfrage, in meinem Fall GET_DOGS, und der Antworttyp (DogsResponseData). Dieser Hook gibt drei Dinge zurück, die bei jedem, der schon einmal eine API abgefragt hat, eine Augenbraue hochziehen sollten: loading, error and data.

Das erste ist ein Boolean - wenn es wahr ist, sollten wir eine Art von Ladekomponente anzeigen. Das zweite ist eine Instanz von ApolloError - wenn es nicht nullish ist, bedeutet es, dass etwas schief gelaufen ist und der Benutzer eine entsprechende Rückmeldung erhalten sollte. Wenn beides false ist, bedeutet das, dass wir die Daten endlich auspacken und in der UI anzeigen können:

Nach diesen Änderungen sieht die gesamte Komponente wie folgt aus:

Meiner Meinung nach sieht das schon aufgeräumt genug aus, aber wenn wir ganz Marie Kondo werden wollen, können wir auch separate Dateien für unsere Abfragen und typen erstellen und werfen unsere Abfrage GET_DOGS und geben dort Hund ein.

3.5 Daten auf der Server-Seite abrufen

Hier kommt der letzte Teil der Implementierung, den wir in diesem Blog-Post machen werden: die API auf der Server-Seite abfragen. Dafür brauchen wir ein paar größere Geschütze: apolloClient.js and withApollo.jsx wrapper. Fairerweise muss man sagen, dass ich sie mir nicht selbst ausgedacht habe - sie werden in der offiziellen Hasura & Apollo & Next.js Implementierungsdokumentation rechts here.

Unglücklicherweise geht die Dokumentation davon aus, dass wir eine Authentifizierung (auth0) in unserer Anwendung haben wollen, was im Moment nicht nötig ist, also habe ich mich entschlossen, es in TypeScript zu übersetzen, es ein wenig aufzuräumen und nur das zu belassen, was für unsere einfache Demo notwendig ist.

Bitte beachten Sie, dass wir hier unsere API-URL-Umgebungsvariable (in meinem Fall 's NEXT_PUBLIC_API_HOST) verwenden:

TypeScript-Version des mitApollo-Wrappers war auch nirgends in der offiziellen Dokumentation zu finden, aber glücklicherweise konnte ich ihn in einem sehr hilfreicher Kommentar von samuelcastro zu einem von Next.js GitHub issues.

Wenn wir das erledigt haben, können wir zu unserer _app.tsx und die Initialisierung des ApolloClient dort loswerden, da wir dies von nun an auf Seitenebene tun werden. Wir müssen nicht die ganze Datei löschen, da wir sie wahrscheinlich irgendwann noch brauchen werden. Nach der Bereinigung sollte die Datei etwa so aussehen:

Der nächste Schritt besteht darin, die Logik des Client-Abrufs durch ihre serverseitige Entsprechung zu ersetzen. Wir können den Hund Typ und die Abfrage intakt lassen, aber wir müssen definitiv unseren mitApollo mit ssr auf true und umhüllen die Komponente damit.

Okay, jetzt wird es ein bisschen ernster, aber keine Sorge, wir werden es aufschlüsseln:

First, lassen Sie uns einen Blick auf die getInitialProps Funktion werfen, auf die wir von unserer Hunde Komponente zugreifen. Warum können wir das überhaupt tun, wenn wir diese Komponente selbst geschrieben haben und uns nicht an eine solche Funktion erinnern können? Die Erklärung ist einfach: es ist Next.js und seine Zaubertricks. Wie ich bereits erwähnt habe, haben unsere Routen im Ordner pages/ einen data-fetching superpowers und dies ist einer von ihnen.

Um sie richtig zu nutzen, müssen wir TypeScript glücklich machen, indem wir den Typ unserer Komponente Dogs von ändern:

to

which makes sense, denn getInitialProps ist nur von der Next.js Seite, nicht von einer regulären funktionalen React Komponente. TypeScript weiß jedoch nicht, dass es eine Next.js-Seite betrachtet, auch wenn sie sich im Verzeichnis pages/ befindet, also müssen wir es explizit mitteilen.

Zurück zur Funktion selbst: es handelt sich um eine normale asynchrone Funktion, die auf der Server-Seite ausgeführt wird und Werte zurückgibt, auf die wir auf der Client-Seite zugreifen können. Die Parameter bestehen aus einem Next.js-Kontextobjekt, genannt NextPageContext, das wir mit unserem ApolloClient erweitern. Daher die Definition für den ServerSideProps:

Warum weiß ich, dass der ApolloClient diesen ganz bestimmten Typ hat? Ich habe ihn auf die einfachste Art und Weise erworben - ich habe ihn von der Typdefinition eines Rückgabewerts einer createApolloClient-Funktion kopiert, die wir in unserer lib/apolloClient.js, auch wenn die Datei im einfachen .js-Format vorliegt. Gesegnet seist du TypeScript, gesegnet seist du VSCode.

Dann ist die eigentliche Anfrage recht einfach, wir müssen nur daran denken, den Antworttyp an die Abfragemethode von ApolloClient zu übergeben:

Der einzige Unterschied ist, dass wir tatsächlich await das Ergebnis abwarten und sich nicht mit dem laden beschäftigen. Sobald es angekommen ist, graben wir die tatsächlichen Hunde aus und kehren zu unserer Hunde Komponente zurück, indem wir ihr sagen, dass wir vorher ein Array von Hund typisierten Objekten übergeben werden:

in all seiner Pracht, seiten/hunde.tsx mit Datenabruf auf der Serverseite sieht so aus:

Und das'ist es! Das Ergebnis ist im Grunde dasselbe, der einzige Unterschied besteht darin, dass wir den beim Laden für einen Sekundenbruchteil nicht sehen, wenn wir die Seite aufrufen. Die Daten werden gnädigerweise auf der Server-Seite geholt und in der Komponente gerendert, als ob sie schon immer da wären.

5. Deploy

Don't be shy! Diese hochmoderne Anwendung verdient es definitiv, dass man mit ihr prahlt, also lassen Sie uns damit prahlen. Für das Deployment werden wir uns ein letztes Tool schnappen, das diesen Prozess extrem angenehm machen wird: Vercel. Installieren wir seine CLI global auf unserem Rechner:

und führen diesen kleinen Befehl im Projektverzeichnis aus, um es in der Cloud bereitzustellen:

Ich will euch nicht die Freude an der Interaktion mit Vercel nehmen, also keine Spoiler, wie reibungslos das Ding funktioniert. Nachdem Sie alles erfolgreich eingerichtet haben, müssen Sie noch eine letzte Sache zu Ihrer Produktionsumgebung hinzufügen: Ihre Umgebungsvariablen. Es ist so einfach, wie in den Projekten "Einstellungen" und dann auf die Registerkarte "Umgebungsvariablen" zu gehen und es einfach dort einzufügen.

Boom! Das'ist es wirklich. Du hast soeben eine Full-Stack-JamStack-Anwendung mit Routen, TypeScript, CI/CD, GraphQL-API und SSR erstellt, du Verrückter! Aber die Show muss auf jeden Fall weitergehen - in den nächsten Blog-Posts werden wir unserem Hundeheim weitere CRUD-Operationen hinzufügen, unsere Flügel mit GraphQL & Hasura ausbreiten, komplexere Datenabrufszenarien angehen und wer weiß, vielleicht sogar eine einfache UI bauen. Danke fürs Vorbeischauen und bis zum nächsten Mal!


✍️

ABOUT THE AUTHOR

Adrian Pilarczyk

Senior Backend-Entwickler

Beste Freunde von React und TypeScript. Engagierter Medienkonsument: Podcast-Kopf, Kinobesucher, Bücherwurm, immer aufnahmefähig. Liebhaber von MMA & BJJ 🥊.

Sie haben eine Projektidee? Lassen Sie uns darüber reden und sie zum Leben erwecken

Ihre hochqualifizierten Spezialisten sind da. Nehmen Sie Kontakt auf, um zu sehen, was wir gemeinsam tun können.

Dariusz Michalski

Dariusz Michalski, CEO

dariusz@useo.pl

Konrad Pochodaj

Konrad Pochodaj, CGO

konrad@useo.pl

Sie haben eine Projektidee? Lassen Sie uns darüber reden und sie zum Leben erwecken

Ihre hochqualifizierten Spezialisten sind da. Nehmen Sie Kontakt auf, um zu sehen, was wir gemeinsam tun können.

Dariusz Michalski

Dariusz Michalski, CEO

dariusz@useo.pl

Konrad Pochodaj

Konrad Pochodaj, CGO

konrad@useo.pl

Sie haben eine Projektidee? Lassen Sie uns darüber reden und sie zum Leben erwecken

Ihre hochqualifizierten Spezialisten sind da. Nehmen Sie Kontakt auf, um zu sehen, was wir gemeinsam tun können.

©2009 - 2025 Useo sp. z o.o.