This is a step-by-step walkthrough of developing a feature from scratch, taking advantage of the most commonly used Clutch capabilities across the frontend and backend. Familiarity with concepts from the Architecture Reference will help, so it is recommended to skim there first, or refer back to it throughout this tutorial.
⏲️ Estimated time to complete: ~30 minutes
This guide should work for a custom gateway or Clutch core as the directory structure is the same for both. In general, starting with a custom gateway is a good idea and recommended for this guide.
If you get lost at any point all of the files referenced in this tutorial can be found in the examples.
The goal of this tutorial is to build a visual search on top of AmiiboAPI.
Users will start by searching for the name of the item they are interested in. Users can search with a simple text query.
The search will return a list of results, after which the user can pick a single result to see full details on.
Start by creating a low fidelity wireframe of the new feature. This helps to gather requirements and feedback from stakeholders as well as focus the implementation.
From the diagram, it's clear that there is only one API endpoint to define. The user provides input on the first step and sees a list of results on the second step.
Now it's time to determine how information will be presented to the frontend from the backend.
In this example, it would be easy enough to call the API directly from the frontend. However, in order to illustrate Clutch concepts, all calls will be proxied through the Clutch backend. This would normally provide authentication, authorization, auditing, logging, stats, additional input validation, API token handling, etc, none of which are strictly needed for this example. Following the guide should reinforce Clutch concepts albeit with a toy example.
For the reasons stated above, the API defined below will largely look identical to the provider's API.
Clutch uses protobuf for interface definitions. An empty definition is provided below.
- The path of the API file should correspond to the path of the API itself. e.g.
- The header of the file will always starts with the
syntaxspecifier. Clutch always uses
packagedirective will also map directly to the filename.
go_packageoption make importing multiple packages a little less confusing by giving a default import name other than
serviceis the group of APIs that share the same underlying
structand defines the gRPC service.
Next, add the endpoint definitions, including the Google API annotation. Added lines are highlighted below.
- Clutch always uses
postfor the method to simplify the mapping between gRPC and HTTP endpoint names.
Now fill in the request and response. protoc-gen-validate message options are used for input validation. Added lines are highlighted below.
- Only use input validation on input objects. Input validation is superfluous on response objects.
With the API definition complete, the code can be generated for the frontend and backend. From the Clutch root, run:
The resulting generated code will be in:
frontend/api/src/index.js, the unified bundle of all frontend generated objects.
On the backend, a
service is needed to interact with the API and a
module is needed to service the API endpoints defined in protobuf.
The module is the implementation of the API endpoints defined in the protobuf.
Services are reuseable clients for external data or services. In that way, this example is a bit contrived for the purposes of illustrating Clutch concepts.
It is acceptable to call the third-party service directly from the module to simplify the code if there is no need for substitution via interface or there are not multiple modules calling into a service. Refactoring from a combined module is not that hard if the need does arise in the future.
The service code is fairly straightforward, especially if you're familiar with Go. Of note are the
New method and the
Name. The signature of
New is the same for every service, and makes the service usable in the Clutch configuration.
Also note that the
Client interface freely makes use of the generated objects from the API.
The module is instantiated after the service when the gateway starts. This allows the module to fetch a reference to any services it needs, which are then stored on the module instance for use during requests.
The module and service must be in the component list at compile time in order for the binary to be able to read instantiate them from config based on their respective names.
Add the components to the config.
Run the gateway with the new components:
With the gateway still running, try the following in a separate shell:
A number of results should appear in the terminal. Also try passing an empty name to see how input validation is automatically applied from the protobuf annotation of the field.
The frontend consists of a few pieces that work together to display your workflow to users. Workflows are exposed via a registration function containing default configuration values and workflow specific properties. One of these properties is the component that should be rendered for this workflow. Once we have that component we need to register the new workflow on the Clutch application.
To simplify the creation of workflows you can run a scaffolding tool. It will prompt you for some information and produce a new workflow with some templates.
To get started run the generator and provide the details about our Amiibo workflow.
You should now have a new Amiibo workflow in the destination directory outlined in the CLI. However, this scaffolding left behind some default values that we should update.
Let's update the component.
Define a functional component for the amiibo lookup by adding the highlighted lines.
This will present a text field which updates a data layout called
userInput on changes and a button for users to click when they are ready to search.
Now let's build a way to display the details panel.
amiiboData data layout has been hydrated a table will be displayed with all amiibo matching the input criteria.
Let's tie these two components together.
Here we define the data layout structure and pass it to the wizard along with the functional components we built above as children.
The final step is registering this new Amiibo workflow with the Clutch app. First update the component name by replacing the scaffolded default (
HelloWorld) in our workflow's registration function.
Next, open your
clutch.config.js file and add the following:
If everything is in order you should see an Amiibo card on the homepage that you can use to access your workflow!
That's it! You should be able to remove all the remaining generated code.
Run the frontend with the new workflow:
You should now be able to navigate to
http://localhost:3000/amiibo/lookup to see your new workflow.
Peach into the input field and clicking search.
Though not available yet, a future guide will cover how to incorporate the resolver pattern.