Editor’s note: We’ve made some big changes to Framer, and this article refers to a deprecated tool. Learn more about what Framer is today →
Here at Onefootball, we see prototypes as more than a single step in our workflow, but as a holistic way for designers to express themselves in a more realistic way. Ultimately, prototyping allows us to capture the feeling of a design and better communicate it across teams. As a design tool, Framer allows us to incorporate a higher level of detail, which is especially useful when building a prototype for user testing purposes. Our prototypes often contain large amounts of data, which often makes them indistinguishable from our real app. In this article, I will show you how we hooked our search API into a prototype and help you build a small example alongside it.
👉 Note: I’m no coding hero so if my code is bad, it’s fine. I just hack my way through to make my prototype work 🙌
😎 Story Time
Onboarding is an important consideration for any app. It’s the first touchpoint between a new user and your product, so it has to be as good as it can be. Otherwise you risk losing users before they have even started. Our old onboarding had a high completion rate, but didn’t do enough to explain the app during the first session. Our search bar wasn’t visible enough and ended up getting skipped by users. As our user testing proved, we needed to consider a different approach to onboarding our potential new users. So we redesigned our onboarding flow with the goal of making it more explanatory for users upon their first session.
The easiest way to test and validate our new onboarding flow was to design a full-fledged prototype that we could then use in a testing session. The project was a collaboration between our Design and Research teams. To make it real, we hooked it up to live data, which in our case was the Search API. The goal was to allow participants to easily find their teams, upon which a search query value would return a JSON list with accurate results.
Or interact with the Framer prototype itself →
💪 Let’s dig in
My challenge here was to be able to take the input from the keyboard and update it every time a new letter is inputed, so mainly it can be broken into the following parts:
👉 Note: The prototype isn’t new and was created long before Framer Design, so don’t panic if you don’t see the Design tab 😉
👉 Note: Framer offers a 14 day free trial, so you can download that to follow along with this tutorial.
1- Use the handy Input Module
Adria Jimenez offers an input module which you can find here: https://github.com/ajimix/Input-Framer
InputModule = require 'input'
Or use a newer version by Benjamin den Boer, which is much easier and better: https://github.com/benjamindenboer/FramerInput
2- Catch input via keyup event & parse API with Utils.domLoadDataSync
Get new search values and use it to update the results list by parsing what we get back from Search using Framer’s built-in utility Utils.domLoadDataSync
inputSearch.on "keyup", ->
searchAPI = JSON.parse Utils.domLoadDataSync "https://search-api.onefootball.com/v1/en/search?q=" + @value
3- Create and manage results list
Loop through results of teams only. The API returns the competition as well, which is not what we are interested in. To get around this, I used a factory function to create a list of teams as you can see in the code below:
if resultArray.length > 0
for i in [0...resultArray.length]
resultArray[i].destroy()for i in [0...searchAPI.teams.length]
itemResult = searchResultFactory(searchAPI.teams[i])
resultArray.push(itemResult)
👩💻 So let’s build something?
Now that we have an understanding of how it should work, lets build a prototype with the knowledge we acquired.
1- Let’s setup the project and the layers
👉 Note: I decided to go with Benjamin’s version of the input field because it’s easier to implement, find it here: https://github.com/benjamindenboer/FramerInput
# Require input module
{InputLayer} = require "input"
We’ll need an array to store the results and be able to manage them easily.
resultArray = []
Some basic setup for search UI is also needed, it can be done in design view. For more information, check out this video by Benjamin:
# setup Layers
input = new InputLayer
x: Align.center
y: 20
width: Screen.width - 30
height: 40
backgroundColor: "#f1f2f4"
text: "Search Teams"
borderRadius: 40
fontSize: 28
fontWeight: 500
color: "#aaa"
padding:
left: 20
To make it even fancier, we can show the number of results:
numberOfResults = new TextLayer
text: '0 Results'
y: 70
x: 15
color: "#aaa"
fontSize: 11
This is how it should look like:
2- Factory function to build search results list
So we need to create and manage a list, which could be done manually. Since we don’t know what the results will be, it has to be handled dynamically. It’s a basic one just to display the team’s logo and name. The function takes two arguments; api
, which is a single result from the search API and index
, which are the results that can dynamically position the item on screen, to avoid them stacking up.
teamFactory = (api, index) ->
team = new Layer
x: Align.center
y: (50 * index) + 100
width: Screen.width - 30
backgroundColor: 'transparent'
height: 40 logo = new Layer
x: 0
y: Align.center
width: 30
height: 30
image: api.images[0].url
parent: team name = new TextLayer
x: logo.width + 10
y: Align.center
text: api.name
color: 'black'
fontSize: 14
parent: team return team
3- Hookup event and Search API
Now we are ready to drop in the search API and hookup the events.
input.on "keyup", ->
# hook up search API
searchAPI = JSON.parse Utils.domLoadDataSync "https://search-api.onefootball.com/v1/en/search?q=" + @value
4- Update number of results layer
It’s initialised to 0, so we need to check if there are any results first and then based on that, we can add the length of that results list and update the numbers.
if searchAPI.teams.length > 0
numberOfResults.text = searchAPI.teams.length + " Results"
5- Display search results in a list
Now let’s display the teams themselves with the help of our factory function we created earlier.
for i in [0...searchAPI.teams.length]
# passing team and index to generate layers to be displayed
team = teamFactory(searchAPI.teams[i], i)
resultArray.push(team)
6- Remove old results list
Remember that each time we create a list to display the teams, it is outdated as soon as there’s a new list that’s created because of a new search value.
for i in [0...resultArray.length]
resultArray[i].destroy()
Here’s the final result with the link to the prototype down below:
Thanks for reading and I hope it was useful. I’m Zero & I’m currently a Product Designer at Onefootball. Check out my website and portfolio.