I’ve very excited to have this feature released for CodePen. It’s very progressive enhancement friendly in the sense that you can take any
block of HTML, CSS, and JavaScript (or any combination of them) and enhance it into an embed, meaning you can see the rendered output. It also lets you pass in stuff like external resources, making it a great choice for, say, documentation sites or the like.
Here’s a wonderful post by Nicolas Chevobbe on what the Firefox DevTools team was up to last year. What strikes me is how many improvements they shipped — from big visual design improvements to tiny usability fixes that help us make sure our code works as we expect it to in the console.
There are lots of interesting hints here about the future of Firefox DevTools, too. For example, tighter integrations with MDN and, as Nicolas mentions in that post, tools to make it feel like a playground where you can improve your design, rather just fixing things. Anyway, I already feel that Firefox DevTools has the best features for typography of any browser (make sure to check out the “Fonts” tab in the Inspector). I can’t wait to see what happens next!
An API is the communication channel for an application to load data from the server. In the world of APIs, REST has been the more established methodology, but has lately been overshadowed by GraphQL, which offers important advantages over REST. Whereas REST requires multiple HTTP requests to fetch a set of data to render a component, GraphQL can query and retrieve such data in a single request, and the response will be exactly what is required, without over or under-fetching data as typically happens in REST.
In this article, I will describe another way of fetching data which I have designed and called “PoP” (and open sourced here), which expands on the idea of fetching data for several entities in a single request introduced by GraphQL and takes it a step further, i.e. while REST fetches the data for one resource, and GraphQL fetches the data for all resources in one component, the component-based API can fetch the data for all resources from all components in one page.
Using a component-based API makes most sense when the website is itself built using components, i.e. when the webpage is iteratively composed of components wrapping other components until, at the very top, we obtain a single component that represents the page. For instance, the webpage shown in the image below is built with components, which are outlined with squares:
A component-based API is able to make a single request to the server by requesting the data for all of the resources in each component (as well as for all of the components in the page) which is accomplished by keeping the relationships among components in the API structure itself.
Among others, this structure offers the following several benefits:
A page with many components will trigger only one request instead of many;
Data shared across components can be fetched only once from the DB and printed only once in the response;
It can greatly reduce — even completely remove — the need for a data store.
We will explore these in details throughout the article, but first, let’s explore what components actually are and how we can build a site based on such components, and finally, explore how a component-based API works.
A component is simply a set of pieces of HTML, JavaScript and CSS code put all together to create an autonomous entity. This can then wrap other components to create more complex structures, and be itself wrapped by other components, too. A component has a purpose, which can range from something very basic (such as a link or a button) to something very elaborate (such as a carousel or a drag-and-drop image uploader). Components are most useful when they are generic and enable customization through injected properties (or “props”), so that they can serve a wide array of use cases. In the utmost case, the site itself becomes a component.
The term “component” is often used to refer both to functionality and design. For instance, concerning functionality, JavaScript frameworks such as React or Vue allow to create client-side components, which are able to self-render (for instance, after the API fetches their required data), and use props to set configuration values on their wrapped components, enabling code reusability. Concerning design, Bootstrap has standardized how websites look and feel through its front-end component library, and it has become a healthy trend for teams to create design systems to maintain their websites, which allows the different team members (designers and developers, but also marketers and salesmen) to speak a unified language and express a consistent identity.
Componentizing a site then is a very sensible way to make the website become more maintainable. Sites using JavaScript frameworks such as React and Vue are already component-based (at least on the client-side). Using a component library like Bootstrap doesn’t necessarily make the site be component-based (it could be a big blob of HTML), however, it incorporates the concept of reusable elements for the user interface.
If the site is a big blob of HTML, for us to componentize it we must break the layout into a series of recurring patterns, for which we must identify and catalogue sections on the page based on their similarity of functionality and styles, and break these sections down into layers, as granular as possible, attempting to have each layer be focused on a single goal or action, and also trying to match common layers across different sections.
Note: Brad Frost’s “Atomic Design” is a great methodology for identifying these common patterns and building a reusable design system.
Hence, building a site through components is akin to playing with LEGO. Each component is either an atomic functionality, a composition of other components, or a combination of the two.
As shown below, a basic component (an avatar) is iteratively composed by other components until obtaining the webpage at the top:
The Component-Based API Specification
For the component-based API I have designed, a component is called a “module”, so from now on the terms “component” and “module” are used interchangeably.
The relationship of all modules wrapping each other, from the top-most module all the way down to the last level, is called the “component hierarchy”. This relationship can be expressed through an associative array (an array of key => property) on the server-side, in which each module states its name as the key attribute and its inner modules under the property modules. The API then simply encodes this array as a JSON object for consumption:
The relationship among modules is defined on a strictly top-down fashion: a module wraps other modules and knows who they are, but it doesn’t know — and doesn’t care — which modules are wrapping him.
For instance, in the JSON code above, module module-level1 knows it wraps modules module-level11 and module-level12, and, transitively, it also knows it wraps module-level121; but module module-level11 doesn’t care who is wrapping it, consequently is unaware of module-level1.
Having the component-based structure, we can now add the actual information required by each module, which is categorized into either settings (such as configuration values and other properties) and data (such as the IDs of the queried database objects and other properties), and placed accordingly under entries modulesettings and moduledata:
Following, the API will add the database object data. This information is not placed under each module, but under a shared section called databases, to avoid duplicating information when two or more different modules fetch the same objects from the database.
In addition, the API represents the database object data in a relational manner, to avoid duplicating information when two or more different database objects are related to a common object (such as two posts having the same author). In other words, database object data is normalized.
This JSON object is already the response from the component-based API. Its format is a specification all by itself: As long as the server returns the JSON response in its required format, the client can consume the API independently of how it is implemented. Hence, the API can be implemented on any language (which is one of the beauties of GraphQL: being a specification and not an actual implementation has enabled it to become available in a myriad of languages.)
Note: In an upcoming article, I will describe my implementation of the component-based API in PHP (which is the one available in the repo).
API response example
For instance, the API response below contains a component hierarchy with two modules, page => post-feed, where module post-feed fetches blog posts. Please notice the following:
Each module knows which are its queried objects from property dbobjectids (IDs 4 and 9 for the blog posts)
Each module knows the object type for its queried objects from property dbkeys (each post’s data is found under posts, and the post’s author data, corresponding to the author with the ID given under the post’s property author, is found under users)
Because the database object data is relational, property author contains the ID to the author object instead of printing the author data directly.
Differences Fetching Data From Resource-Based, Schema-Based And Component-Based APIs
Let’s see how a component-based API such as PoP compares, when fetching data, to a resource-based API such as REST, and to a schema-based API such as GraphQL.
Let’s say IMDB has a page with two components which need to fetch data: “Featured director” (showing a description of George Lucas and a list of his films) and “Films recommended for you” (showing films such as Star Wars: Episode I — The Phantom Menace and The Terminator). It could look like this:
Let’s see how many requests are needed to fetch the data through each API method. For this example, the “Featured director” component brings one result (“George Lucas”), from which it retrieves two films (Star Wars: Episode I — The Phantom Menace and Star Wars: Episode II — Attack of the Clones), and for each film two actors (“Ewan McGregor” and “Natalie Portman” for the first film, and “Natalie Portman” and “Hayden Christensen” for the second film). The component “Films recommended for you” brings two results (Star Wars: Episode I — The Phantom Menace and The Terminator), and then fetches their directors (“George Lucas” and “James Cameron” respectively).
Using REST to render component featured-director, we may need the following 7 requests (this number can vary depending on how much data is provided by each endpoint, i.e. how much over-fetching has been implemented):
GET - /featured-director
GET - /directors/george-lucas
GET - /films/the-phantom-menace
GET - /films/attack-of-the-clones
GET - /actors/ewan-mcgregor
GET - /actors/natalie-portman
GET - /actors/hayden-christensen
GraphQL allows, through strongly typed schemas, to fetch all the required data in one single request per component. The query to fetch data through GraphQL for the component featuredDirector looks like this (after we have implemented the corresponding schema):
query {
featuredDirector {
name
country
avatar
films {
title
thumbnail
actors {
name
avatar
}
}
}
}
PoP will issue only one request to fetch all the data for all components in the page, and normalize the results. The endpoint to be called is simply the same as the URL for which we need to get the data, just adding an additional parameter output=json to indicate to bring the data in JSON format instead of printing it as HTML:
GET - /url-of-the-page/?output=json
Assuming that the module structure has a top module named page containing modules featured-director and films-recommended-for-you, and these also have submodules, like this:
Let’s analyze how these three methods compare to each other, in terms of speed and the amount of data retrieved.
Speed
Through REST, having to fetch 7 requests just to render one component can be very slow, mostly on mobile and shaky data connections. Hence, the jump from REST to GraphQL represents a great deal for speed, because we are able to render a component with only one request.
PoP, because it can fetch all data for many components in one request, will be faster for rendering many components at once; however, most likely there is no need for this. Having components be rendered in order (as they appear in the page), is already a good practice, and for those components which appear under the fold there is certainly no rush to render them. Hence, both the schema-based and component-based APIs are already pretty good and clearly superior to a resource-based API.
Amount of Data
On each request, data in the GraphQL response may be duplicated: actress “Natalie Portman” is fetched twice in the response from the first component, and when considering the joint output for the two components, we can also find shared data, such as film Star Wars: Episode I — The Phantom Menace.
PoP, on the other hand, normalizes the database data and prints it only once, however, it carries the overhead of printing the module structure. Hence, depending on the particular request having duplicated data or not, either the schema-based API or the component-based API will have a smaller size.
In conclusion, a schema-based API such as GraphQL and a component-based API such as PoP are similarly good concerning performance, and superior to a resource-based API such as REST.
If a component-based API is not necessarily better in terms of performance than a schema-based API, you may be wondering, then what am I trying to achieve with this article?
In this section, I will attempt to convince you that such an API has incredible potential, providing several features which are very desirable, making it a serious contender in the world of APIs. I describe and demonstrate each of its unique great features below.
The Data To Be Retrieved From The Database Can Be Inferred From The Component Hierarchy
When a module displays a property from a DB object, the module may not know, or care, what object it is; all it cares about is defining what properties from the loaded object are required.
For instance, consider the image below. A module loads an object from the database (in this case, a single post), and then its descendant modules will show certain properties from the object, such as title and content:
Hence, along the component hierarchy, the “dataloading” modules will be in charge of loading the queried objects (the module loading the single post, in this case), and its descendant modules will define what properties from the DB object are required (title and content, in this case).
Fetching all the required properties for the DB object can be done automatically by traversing the component hierarchy: starting from the dataloading module, we iterate all its descendant modules all the way down until reaching a new dataloading module, or until the end of the tree; at each level we obtain all required properties, and then merge all properties together and query them from the database, all of them only once.
In the structure below, module single-post fetches the results from the DB (the post with ID 37), and submodules post-title and post-content define properties to be loaded for the queried DB object (title and content respectively); submodules post-layout and fetch-next-post-button do not require any data fields.
"single-post"
=> Load objects with object type "post" and ID 37
modules
"post-layout"
modules
"post-title"
=> Load property "title"
"post-content"
=> Load property "content"
"fetch-next-post-button"
The query to be executed is calculated automatically from the component hierarchy and their required data fields, containing all the properties needed by all the modules and their submodules:
SELECT
title, content
FROM
posts
WHERE
id = 37
By fetching the properties to retrieve directly from the modules, the query will be automatically updated whenever the component hierarchy changes. If, for instance, we then add submodule post-thumbnail, which requires data field thumbnail:
"single-post"
=> Load objects with object type "post" and ID 37
modules
"post-layout"
modules
"post-title"
=> Load property "title"
"post-content"
=> Load property "content"
"post-thumbnail"
=> Load property "thumbnail"
"fetch-next-post-button"
Then the query is automatically updated to fetch the additional property:
SELECT
title, content, thumbnail
FROM
posts
WHERE
id = 37
Because we have established the database object data to be retrieved in a relational manner, we can also apply this strategy among the relationships between database objects themselves.
Consider the image below: Starting from the object type post and moving down the component hierarchy, we will need to shift the DB object type to user and comment, corresponding to the post’s author and each of the post’s comments respectively, and then, for each comment, it must change the object type once again to user corresponding to the comment’s author.
Moving from a database object to a relational object (possibly changing the object type, as in post => author going from post to user, or not, as in author => followers going from user to user) is what I call “switching domains”.
After switching to a new domain, from that level at the component hierarchy downwards, all required properties will be subjected to the new domain:
name is fetched from the user object (representing the post’s author),
content is fetched from the comment object (representing each of the post’s comments),
name is fetched from the user object (representing the author of each comment).
Traversing the component hierarchy, the API knows when it is switching to a new domain and, appropriately, update the query to fetch the relational object.
For example, if we need to show data from the post’s author, stacking submodule post-author will change the domain at that level from post to the corresponding user, and from this level downwards the DB object loaded into the context passed to the module is the user. Then, submodules user-name and user-avatar under post-author will load properties name and avatar under the user object:
"single-post"
=> Load objects with object type "post" and ID 37
modules
"post-layout"
modules
"post-title"
=> Load property "title"
"post-content"
=> Load property "content"
"post-author"
=> Switch domain from "post" to "user", based on property "author"
modules
"user-layout"
modules
"user-name"
=> Load property "name"
"user-avatar"
=> Load property "avatar"
"fetch-next-post-button"
Resulting in the following query:
SELECT
p.title, p.content, p.author, u.name, u.avatar
FROM
posts p
INNER JOIN
users u
WHERE
p.id = 37 AND p.author = u.id
In summary, by configuring each module appropriately, there is no need to write the query to fetch data for a component-based API. The query is automatically produced from the structure of the component hierarchy itself, obtaining what objects must be loaded by the dataloading modules, the fields to retrieve for each loaded object defined at each descendant module, and the domain switching defined at each descendant module.
Adding, removing, replacing or altering any module will automatically update the query. After executing the query, the retrieved data will be exactly what is required — nothing more or less.
Observing Data And Calculating Additional Properties
Starting from the dataloading module down the component hierarchy, any module can observe the returned results and calculate extra data items based on them, or feedback values, which are placed under entry moduledata.
For instance, module fetch-next-post-button can add a property indicating if there are more results to fetch or not (based on this feedback value, if there aren’t more results, the button will be disabled or hidden):
Implicit Knowledge Of Required Data Decreases Complexity And Makes The Concept Of An “Endpoint” Become Obsolete
As shown above, the component-based API can fetch exactly the required data, because it has the model of all components on the server and what data fields are required by each component. Then, it can make the knowledge of the required data fields implicit.
The advantage is that defining what data is required by the component can be updated just on the server-side, without having to redeploy JavaScript files, and the client can be made dumb, just asking the server to provide whatever data it is that it needs, thus decreasing the complexity of the client-side application.
In addition, calling the API to retrieve the data for all components for a specific URL can be carried out simply by querying that URL plus adding the extra parameter output=json to indicate returning API data instead of printing the page. Hence, the URL becomes its own endpoint or, considered in a different way, the concept of an “endpoint” becomes obsolete.
Retrieving Subsets Of Data: Data Can Be Fetched For Specific Modules, Found At Any Level Of The Component Hierarchy
What happens if we don’t need to fetch the data for all modules in a page, but simply the data for a specific module starting at any level of the component hierarchy? For instance, if a module implements an infinite-scroll, when scrolling down we must fetch only new data for this module, and not for the other modules on the page.
This can be accomplished by filtering the branches of the component hierarchy that will be included in the response, to include properties only starting from the specified module and ignore everything above this level. In my implementation (which I will describe in an upcoming article), the filtering is enabled by adding parameter modulefilter=modulepaths to the URL, and the selected module (or modules) is indicated through a modulepaths[] parameter, where a “module path” is the list of modules starting from the top-most module to the specific module (e.g. module1 => module2 => module3 has module path [module1, module2, module3] and is passed as a URL parameter as module1.module2.module3).
For instance, in the component hierarchy below every module has an entry dbobjectids:
Then requesting the webpage URL adding parameters modulefilter=modulepaths and modulepaths[]=module1.module2.module5 will produce the following response:
In essence, the API starts loading data starting from module1 => module2 => module5. That’s why module6, which comes under module5, also brings its data while module3 and module4 do not.
In addition, we can create custom module filters to include a pre-arranged set of modules. For instance, calling a page with modulefilter=userstate can print only those modules which require user state for rendering them in the client, such as modules module3 and module6:
Similar to module filters userstate and page described above, we can implement any custom module filter and create rich user experiences.
The Module Is Its Own API
As shown above, we can filter the API response to retrieve data starting from any module. As a consequence, every module can interact with itself from client to server just by adding its module path to the webpage URL in which it has been included.
I hope you will excuse my over-excitement, but I truly can’t emphasize enough how wonderful this feature is. When creating a component, we don’t need to create an API to go alongside with it to retrieve data (REST, GraphQL, or anything at all), because the component is already able to talk to itself in the server and load its own data — it is completely autonomous and self-serving.
Each dataloading module exports the URL to interact with it under entry dataloadsource from under section datasetmodulemeta:
To make my point that fetching data in a component-based API is highly decoupled and DRY (Don’t Repeat Yourself), I will first need to show how in a schema-based API such as GraphQL it is less decoupled and not DRY.
In GraphQL, the query to fetch data must indicate the data fields for the component, which may include subcomponents, and these may also include subcomponents, and so on. Then, the topmost component needs to know what data is required by every one of its subcomponents too, as to fetch that data.
For instance, rendering the component might require the following subcomponents:
In this scenario, the GraphQL query is implemented at the level. Then, if subcomponent is updated, requesting the title through property filmTitle instead of title, the query from the component will need to be updated, too, to mirror this new information (GraphQL has a versioning mechanism which can deal with this problem, but sooner or later we should still update the information). This produces maintenance complexity, which could be difficult to handle when the inner components often change or are produced by third-party developers. Hence, components are not thoroughly decoupled from each other.
Similarly, we may want to render directly the component for some specific film, for which then we must also implement a GraphQL query at this level, to fetch the data for the film and its actors, which adds redundant code: portions of the same query will live at different levels of the component structure. So GraphQL is not DRY.
Because a component-based API already knows how its components wrap each other in its own structure, then these problems are completely avoided. For one, the client is able to simply request the required data it needs, whichever this data is; if a subcomponent data field changes, the overall model already knows and adapts immediately, without having to modify the query for the parent component in the client. Therefore, the modules are highly decoupled from each other.
For another, we can fetch data starting from any module path, and it will always return the exact required data starting from that level; there are no duplicated queries whatsoever, or even queries to start with. Hence, a component-based API is fully DRY. (This is another feature that really excites me and makes me get wet.)
(Yes, pun fully intended. Sorry about that.)
Retrieving Configuration Values In Addition To Database Data
Let’s revisit the example of the featured-director component for the IMDB site described above, which was created — you guessed it! — with Bootstrap. Instead of hardcoding the Bootstrap classnames or other properties such as the title’s HTML tag or the avatar max width inside of JavaScript files (whether they are fixed inside the component, or set through props by parent components), each module can set these as configuration values through the API, so that then these can be directly updated on the server and without the need to redeploy JavaScript files. Similarly, we can pass strings (such as the title Featured director) which can be already translated/internationalized on the server-side, avoiding the need to deploy locale configuration files to the front-end.
Similar to fetching data, by traversing the component hierarchy, the API is able to deliver the required configuration values for each module and nothing more or less.
The configuration values for the featured-director component might look like this:
Please notice how — because the configuration properties for different modules are nested under each module’s level — these will never collide with each other if having the same name (e.g. property classes from one module will not override property classes from another module), avoiding having to add namespaces for modules.
Higher Degree Of Modularity Achieved In The Application
The degree to which a system’s components may be separated and recombined, often with the benefit of flexibility and variety in use. The concept of modularity is used primarily to reduce complexity by breaking a system into varying degrees of interdependence and independence across and ‘hide the complexity of each part behind an abstraction and interface’.
Being able to update a component just from the server-side, without the need to redeploy JavaScript files, has the consequence of better reusability and maintenance of components. I will demonstrate this by re-imagining how this example coded for React would fare in a component-based API.
Let’s say that we have a component, currently with two items: and , like this:
Render <ShareOnSocialMedia>:
<ul>
<li>Share on Facebook: <FacebookShare url={window.location.href} /></li>
<li>Share on Twitter: <TwitterShare url={window.location.href} /></li>
</ul>
But then Instagram got kind of cool, so we need to add an item to our component, too:
Render <ShareOnSocialMedia>:
<ul>
<li>Share on Facebook: <FacebookShare url={window.location.href} /></li>
<li>Share on Twitter: <TwitterShare url={window.location.href} /></li>
<li>Share on Instagram: <InstagramShare url={window.location.href} /></li>
</ul>
In the React implementation, as it can be seen in the linked code, adding a new component under component forces to redeploy the JavaScript file for the latter one, so then these two modules are not as decoupled as they could be.
In the component-based API, though, we can readily use the relationships among modules already described in the API to couple the modules together. While originally we will have this response:
And just by iterating all the values under modulesettings["share-on-social-media"].modules, component can be upgraded to show the component without the need to redeploy any JavaScript file. Hence, the API supports the addition and removal of modules without compromising code from other modules, attaining a higher degree of modularity.
Native Client-Side Cache/Data Store
The retrieved database data is normalized in a dictionary structure, and standardized so that, starting from the value on dbobjectids, any piece of data under databases can be reached just by following the path to it as indicated through entries dbkeys, whichever way it was structured. Hence, the logic for organizing data is already native to the API itself.
We can benefit from this situation in several ways. For instance, the returned data for each request can be added into a client-side cache containing all data requested by the user throughout the session. Hence, it is possible to avoid adding an external data store such as Redux to the application (I mean concerning the handling of data, not concerning other features such as the Undo/Redo, the collaborative environment or the time-travel debugging).
Also, the component-based structure promotes caching: the component hierarchy depends not on the URL, but on what components are needed in that URL. This way, two events under /events/1/ and /events/2/ will share the same component hierarchy, and the information of what modules are required can be reutilized across them. As a consequence, all properties (other than database data) can be cached on the client after fetching the first event and reutilized from then on, so that only database data for each subsequent event must be fetched and nothing else.
Extensibility And Re-purposing
The databases section of the API can be extended, enabling to categorize its information into customized subsections. By default, all database object data is placed under entry primary, however, we can also create custom entries where to place specific DB object properties.
For instance, if the component “Films recommended for you” described earlier on shows a list of the logged-in user’s friends who have watched this film under property friendsWhoWatchedFilm on the film DB object, because this value will change depending on the logged-in user then we save this property under a userstate entry instead, so when the user logs out, we only delete this branch from the cached database on the client, but all the primary data still remains:
In addition, up to a certain point, the structure of the API response can be re-purposed. In particular, the database results can be printed in a different data structure, such as an array instead of the default dictionary.
For instance, if the object type is only one (e.g. films), it can be formatted as an array to be fed directly into a typeahead component:
[
{
title: "Star Wars: Episode I - The Phantom Menace",
thumbnail: "..."
},
{
title: "Star Wars: Episode II - Attack of the Clones",
thumbnail: "..."
},
{
title: "The Terminator",
thumbnail: "..."
},
]
Support For Aspect-Oriented Programming
In addition to fetching data, the component-based API can also post data, such as for creating a post or adding a comment, and execute any kind of operation, such as logging the user in or out, sending emails, logging, analytics, and so on. There are no restrictions: any functionality provided by the underlying CMS can be invoked through a module — at any level.
Along the component hierarchy, we can add any number of modules, and each module can execute its own operation. Hence, not all operations must necessarily be related to the expected action of the request, as when doing a POST, PUT or DELETE operation in REST or sending a mutation in GraphQL, but can be added to provide extra functionalities, such as sending an email to the admin when a user creates a new post.
So, by defining the component hierarchy through dependency-injection or configuration files, the API can be said to support Aspect-oriented programming, “a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns.”
The names of the modules are not necessarily fixed when printed in the output, but can be shortened, mangled, changed randomly or (in short) made variable any way intended. While originally thought for shortening the API output (so that module names carousel-featured-posts or drag-and-drop-user-images could be shortened to a base 64 notation, such as a1, a2 and so on, for the production environment), this feature allows to frequently change the module names in the response from the API for security reasons.
For instance, input names are by default named as their corresponding module; then, modules called username and password, which are to be rendered in the client as and respectively, can be set varying random values for their input names (such as zwH8DSeG and QBG7m6EF today, and c3oMLBjo and c46oVgN6 tomorrow) making it more difficult for spammers and bots to target the site.
Versatility Through Alternative Models
The nesting of modules allows to branch out to another module to add compatibility for a specific medium or technology, or change some styling or functionality, and then return to the original branch.
For instance, let’s say the webpage has the following structure:
In this case, we’d like to make the website also work for AMP, however, modules module2, module4 and module5 are not AMP compatible. We can branch these modules out into similar, AMP-compatible modules module2AMP, module4AMP and module5AMP, after which we keep loading the original component hierarchy, so then only these three modules are substituted (and nothing else):
This makes it fairly easy to generate different outputs from a single codebase, adding forks only here and there as needed, and always scoped and restrained to individual modules.
Demonstration Time
The code implementing the API as explained in this article is available in this open-source repository.
I have deployed the PoP API under https://nextapi.getpop.org for demonstration purposes. The website runs on WordPress, so the URL permalinks are those typical to WordPress. As noted earlier, through adding parameter output=json to them, these URLs become their own API endpoints.
A good API is a stepping stone for creating reliable, easily maintainable and powerful applications. In this article, I have described the concepts powering a component-based API which, I believe, is a pretty good API, and I hope I have convinced you too.
So far, the design and implementation of the API have involved several iterations and taken more than five years — and it’s not completely ready yet. However, it is in a pretty decent state, not ready for production but as a stable alpha. These days, I am still working on it; working on defining the open specification, implementing the additional layers (such as rendering) and writing documentation.
In an upcoming article, I will describe how my implementation of the API works. Until then, if you have any thoughts about it — regardless whether positive or negative — I would love to read your comments below.
New year, new design tools. As your start regrouping and reorganizing in 2019, why not make good on those resolutions and try a new design element or two. We’ve got plenty to choose from here.
If we’ve missed something that you think should have been on the list, let us know in the comments. And if you know of a new app or resource that should be featured next month, tweet it to @carriecousins to be considered!
UI Bundle
UI Bundle is a search tool to help you find fonts, icons, UI kits, mockups and more design goodies. You can browse options right on the home screen or use the search bar to find the perfect set of tools. And the best part? All of the tools and resources are free to download and use.
Rakuten RapidAPI
Rakuten RapidAPI helps you discover and connect to APIs in the world’s largest hub. Search for popular, recommended or task specific APIs, test in-browser and connect using code snippets. Plus, you can manage it all from a single dashboard.
Free Image and Photo Resizer
Free Image and Photo Resizer gets your images ready for website and social media use without expensive software. Just upload your image and the tool will create a crop that fits common social media channels and web specifications. You can also create custom sizes.
SVG Gradient Map Filter
SVG Gradient Map Filter is a nifty little tool that puts a great color overlay on images. You can use ready-made palettes or edit them and get yours.
WebsiteVoice
WebsiteVoice turns text into high-quality audio for users who want to listen to your content. (We all know that voice interfaces are all the rage!) Voice interfaces can increase user engagement, accessibility and help grow followers and subscribers to content. The tool is customizable and free.
Screen.Guru
Screen.Guru takes all the guesswork out of creating clean website screenshots. Just enter a URL and get a grab that you can use in projects.
Blobmaker
Blobmaker helps you create trendy bubbles and blobs for website designs. With plenty of settings to tweak this is as fun to play with as it is useful.
Pika
Pika is a “search engine” for finding modern packages on npm. You can browse and search for smaller, faster JavaScript bundles.
UI Sounds
UI Sounds shows what a noisy place the internet has become. It’s a collection of all the beeps, dings and ditties that are part of our everyday browsing habits.
Magic Sketchpad
Magic Sketchpad uses machine learning to finish your doodles and sketches. It’s pretty addictive to play with.
Essentials Icon Pack
Essentials Icon Pack is a set of common icons that work for pretty much every project. The tool from InVision is based on their most popular icons and includes 140 icons.
Vector Icons
Freebiesbug has a set of 150 vector icons that are free to try. The set includes plenty of icons in multiple categories – weather, music, health, food and more – in colored, outline and monochromatic options. Each comes in AI, EPS and PNG format for easy customization and scalable use.
UI Logos
UI Logos is a collection of free professional logo placeholders for projects. There are more than 25 logos and a plugin to help you get elements that will make your mockups look more polished. It works with Sketch and Adobe XD.
Space Marble Backgrounds
Space Marble Backgrounds is a fun set of background images with a design that’s out of this world! The collection includes 12 handmade options for a variety of project types.
Social Meet Up UI Kit
Social Meet Up UI Kit is a free collection of Adobe XD with more than 80 screens in six categories to speed up your workflow for projects. Everything is customizable and comes with a pretty nifty color and typography palette that you can use (or not).
Design Camera
Design Camera is an app for your Mac that lets you create, capture and animate 3D mockups for your digital designs in a matter of seconds. Designers from Shopify, Google, Starbucks, Uber, Sketch and Dropbox are already in the beta.
CSS Puns
CSS Puns is sure to make you giggle … if you understand code anyway. Play with the tool only or buy merchandise if there’s a pun you really like.
Material Design Palette Generator
Material Design Palette Generator pulls the colors of Material Design out of Google’s documentation for easy use. Turn a hex code into a full palette right on the screen.
Alvaro
Alvaro is a condensed sans serif display font that’s made to be big. It includes 221 characters in an uppercase style.
Classical Monoline Script
Classical is a fun and readable script that has a neutral feel. It includes beautiful upper- and lowercase options as well as alternates, ligatures and swashes.
Honeymoon Avenue Serif Font
Honeymoon Avenue Serif Font is a modern style serif with alternating thin and thick stroke widths. It’s a little on the thin side and is easy to read. The free version includes uppercase letters.
PT Root
PT Root is part of the PT Root typeface family. It includes four styles of normal proportions intended for screen reading, interfaces, websites and wayfinding systems. PT Root is a modern uniwidth sans serif whose individual character widths are constant across all weights.
Soulcraft
Soulcraft is a free OpenType variable font designed with the idea of emulating vernacular lettering. You can change the width and slant of each individual character without relying on pre-defined font weights.
The Rustic
The Rustic is a simple uppercase display typeface in a fun style. It includes alternates for an interesting look.
Every week users submit a lot of interesting stuff on our sister site Webdesigner News, highlighting great content from around the web that can be of interest to web designers.
The best way to keep track of all the great stories and news being posted is simply to check out the Webdesigner News site, however, in case you missed some here’s a quick and useful compilation of the most popular designer news that we curated from the past week.
Note that this is only a very small selection of the links that were posted, so don’t miss out and subscribe to our newsletter and follow the site daily for all the news.
Anime.js
Brutalist Websites are Dead
Tastemaking: 2019 Design Trends
Will Adobe XD Kill Sketch and InVision?
HTML5 Input Types: Where are They Now?
Re: Pleasing Color Palettes
6 Best Drag and Drop WordPress Page Builders Compared (2019)
Why I Don’t Use Google Analytics
Tint and Shade Generator
How to Win all Arguments About Color
Mailtolink.me
Security Checklist
You Pay Me, but I Don’t Work for You
An Egg Beats Kylie Jenner to Become the Most Liked Instagram Photo… Ever
Icons. Good or Bad? As Always, it Depends
The Flexbox Holy Albatross
A Collection of Great UI Designs
Pentagram Case Study on the Slack Rebrand
Should Design Tools Code?
Top 5 Popular Free Material Design Frameworks for Developers
Why Most of 2018’s Tech Predictions were Wrong
What is your UX Process?
Inspiration: Figmas 404 Page
3 UX Takeaways from Redesigning Google Translate
EU Article 13 is Almost Finished – And it will Change the Internet as We Know it
Want more? No problem! Keep track of top design news from around the web with Webdesigner News.
2018 seemed to go by so quickly! But, that doesn’t mean that there’s any shortage of great website designs out there. With more and more websites joining the web every day, it’s actually really hard to find one that stands out. So, for your viewing pleasure, we put together a quick list of the best website designs that stood out to us in 2018. Some of these you may already know, but a few of them might be a surprise.
Epicurence
Anywhere you go on Epicurence is simply a visual delight. The site is packed with fun animations and unique transitions. Not to mention the beautiful colors and eye catching images. It’s hard to pick one single part of Epiccurence that’s better than the other. Well done!
Eleven Plants For Dum-Dums
Now, I know what you’re thinking, and no, this isn’t some super hipster design studio. Eleven plants For Dum-Dums is literally just a website that lists 11 different kinds of plants. What makes it stand out is the use of animation and the color green. It’s a really fun website to visit, and they make each section about each plant so unique, that it’s impossible to look away.
Hello Monday
As much as we all probably dislike Monday, Hello Monday the website is a welcome site. On the main page, the way they transition from story to story is super clean. The transitions are also timed really well. They give you enough time to glimpse the story and click if you want, but they don’t stay up too long and make you feel like you’re staring at a wall.
Feed Music
Feed Music’s main page captures your attention instantly. So much so, that you almost don’t want to click on anything else. The animation is smooth and the colors are beautifully balanced. To top it all off, if you scroll down through the content in the middle of the main page, you feel like you’re watching to intro to a Star Wars movie.
The Sum
Just in case you haven’t read anything else on our blog, we love custom graphics. The Sum takes a very minimalistic approach, but wow are the visuals amazing. Combine that with a sense of humor, and a fast functioning website, and you have yourself a winner.
Zillow
Let’s take a dip into more familiar territory, shall we? Zillow is a pretty common name to hear nowadays, especially if you’re in the real estate business. It’s safe to say that they’re really good at what they do. Another thing that they really nailed is the design of their website. The best website designs are the ones that serve their purpose and look good doing it. Zillow is not only visually appealing, it functions like a champ, and it’s easy to use. What more could you want?
Toggl
Here’s another big name you hear about a lot. What makes Toggl so mind blowing is their weirdly entertaining animations on almost all their pages. Each page provides soft and relaxing colors, and the oever website has such a friendly and helpful tone to it that it’s impossible not to feel at home.
Distance to Mars
Distance to Mars was designed to educate people in a clever way. The website is dedicated to one purpose, showing viewers the distance to mars. Along the way, they’ll provide some scientific facts that are quite entertaining. If you have a few extra seconds, it’s definitely worth checking out.
World of SWISS
World of SWISS is a website dedicated to SWISS airlines. The website i beautiful and clean, but most of all, it perfectly tells a their story. On the main page, you’ll find no shortage of articles and videos describing what it’s like to fly with them. The website’s function is smooth and the visuals are crisp and perfect for the brand. This is a great example of how simplicity and functionality can go a long way.
Juliana Bicycles
As a bicycle site just for women, Juliana Bicycles delivers clean and vibrant images, and outstanding functionality. They take advantage of responsive interactions, and it really works well for the site. It’s colorful, clean, and really really cool.
Guillaume Tomasi
Guillaume Tomasi is a photographer in Montreal that has built a portfolio that’s quite impressive. Both according to its contents and the beautiful manner at which he pulled it off. The website is simply beautiful and is a great example of both how to design a website and portfolio. The interactions are simple but fun, and definitely get the job done. Never once will you feel inconvenienced by the way the website works. It’s simple, but it’s different for sure.
Crypton
Crypton is a robot accountant that helps you buy and sell cryptocurrency. The site uses the best of the best AI to help you predict changes in values for all kinds of cryptocurrencies. Since its creation, it’s been given quite a few awards for its design and development, and you can see why from the moment you click on it.
JOHOs
If you want a website with superb images, nice interactions, quick functionality, and delicate story telling, then look no further than JOHOs. The website tells the story of the brand’s coffee beans. You get to travel along with them from the growing process all the way to the brew. It’s like a mini movie and it’s so mesmerizing to watch.
Apple
We’ll end this list with Apple, a company that has been notorious throughout its existence for creating sleek and functional products, and their website is no different. It’s packed to the brim with high quality imagery and super modern style. The iPhones displayed on the main page all but jump out at you.
Conclusion
The best website designs are not good at any one particular thing. But rather, they’re great at many different things. Each website on this list of best website designs of 2018 showcase many strong advantages that they have over other websites.
Some of the names in this list you may have already been familiar with, and some are probably new to you. Regardless of whether is new news or old news, these websites are simply stunning, and the design teams behind each one have something to be extremely proud of. Go ahead and click on the links are check them out for yourself!
Product teams from AirBnb and New York Times to Shopify and Artsy (among many others) are converging on a new set of best practices and technologies for building the web apps that their businesses depend on. This trend reflects core principles and solve underlying problems that we may share, so it is worth digging deeper.
Internal consistency: Created with static typing tools like TypeScript.
Data manipulation: These work with GraphQL-speaking clients like Apollo.
Data representation: Displayed with a library for reusable components and behaviors, like React.
Naming things is hard, and our industry has struggled to name this new generation of tooling for web apps. The inimitable Orta Theroux calls it an Omakase; I slimmed it down and opted for a simpler backronym pulled from letters in the tooling outlined above: STAR (Design Systems, TypeScript, Apollo, and React).
Hooks make it possible to organize logic in components, making them tiny and reusable without writing a class. In a sense, they’re React’s way of leaning into functions because, before them, we’d have to write them in a component and, while components have proven to be powerful and functional in and of themselves, they have to render something on the front end. That’s all fine and dandy to some extent, but the result is a DOM that is littered with divs that make it gnarly to dig through through DevTools and debug.
Well, React Hooks change that. Instead of relying on the top-down flow of components or abstracting components in various ways, like higher-order components, we can call and manage flow inside of a component. Dan Abramov explains it well in his Making Sense of React post:
Hooks apply the React philosophy (explicit data flow and composition) inside a component, rather than just between the components. That’s why I feel that Hooks are a natural fit for the React component model.
Unlike patterns like render props or higher-order components, Hooks don’t introduce unnecessary nesting into your component tree. They also don’t suffer from the drawbacks of mixins.
The rest of Dan’s post provides a lot of useful context for why the React team is moving in this direction (they’re now available in React v16.7.0-alpha) and the various problems that hooks are designed to solve. The React docs have an introduction to hooks that, in turn, contains a section on what motivated the team to make them. We’re more concerned with how the heck to use them, so let’s move on to some examples!
The important thing to note as we get started is that there are nine hooks currently available, but we’re going to look at what the React docs call the three basic ones: useState(), useEffect, and setContext(). We’ll dig into each one in this post with a summary of the advanced hooks at the end.
Defining state with useState()
If you’ve worked with React at any level, then you’re probably familiar with how state is generally defined: write a class and use this.state to initialize a class:
class SomeComponent extends React.component {
constructor(props)
super(props);
this.state = {
name: Barney Stinson // Some property with the default state value
}
}
React hooks allow us to scrap all that class stuff and put the useState() hook to use instead. Something like this:
import { useState } from 'react';
function SomeComponent() {
const [name, setName] = useState('Barney Stinson'); // Defines state variable (name) and call (setName) -- both of which can be named anything
}
Say what?! That’s it! Notice that we’re working outside of a class. Hooks don’t work inside of a class because they’re used in place of them. We’re using the hook directly in the component:
Oh, you want to update the state of name? Let’s add an input and submit button to the output and call setName to update the default name on submission.
Notice something else in this example? We’re constructing two different states (input and name). That’s because the useState() hook allows managing multiple states in the same component! In this case, input is the property and setValue holds the state of the input element, which is called by the handleInput function then triggers the updateName function that takes the input value and sets it as the new name state.
Create side effects with useEffect()
So, defining and setting states is all fine and dandy, but there’s another hook called useEffect() that can be used to—you guessed it—define and reuse effects directly in a component without the need for a class or the need to use both redundant code for each lifecycle of a method (i.e. componentDidMount, componentDidUpdate, and componentWillUnmount).
When we talk about effects, we’re referring to things like API calls, updates to the DOM, and event listeners, among other things. The React documentation cites examples like data fetching, setting up subscriptions, and changing the DOM as possible use cases for this hook. Perhaps the biggest differentiator from setState() is that useEffect() runs after render. Think of it like giving React an instruction to hold onto the function that passes and then make adjustments to the DOM after the render has happened plus any updates after that. Again, the React documentation spells it out nicely:
By default, it runs both after the first render and after every update. […] Instead of thinking in terms of “mounting” and “updating”, you might find it easier to think that effects happen “after render”. React guarantees the DOM has been updated by the time it runs the effects.
Right on, so how do we run these effects? Well, we start off by importing the hook the way we did for setState().
import { useEffect } from 'react';
In fact, we can call both setState() and useEffect() in the same import:
import { useState, useEffect } from 'react';
Or, construct them:
const { useState, useEffect } = React;
So, let’s deviate from our previous name example by hooking into an external API that contains user data using axios inside the useEffect() hook then renders that data into a list of of users.
First, let’s bring in our hooks and initialize the App.
Now, let’s put setState() to define users as a variable that contains a state of setUsers that we’ll pass the user data to once it has been fetched so that it’s ready for render.
Here’s where useEffect() comes into play. We’re going to use it to connect to an API and fetch data from it, then map that data to variables we can call on render.
const { useState, useEffect } = React
const App = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
// Connect to the Random User API using axios
axios("https://randomuser.me/api/?results=10")
// Once we get a response, fetch name, username, email and image data
// and map them to defined variables we can use later.
.then(response =>
response.data.results.map(user => ({
name: `{user.name.first} ${user.name.last}`,
username: `{user.login.username}`,
email: `{user.email}`,
image: `{user.picture.thumbnail}`
}))
)
// Finally, update the `setUsers` state with the fetched data
// so it stores it for use on render
.then(data => {
setUsers(data);
});
}, []);
// The UI to render
}
It’s worth noting that useEffect() is capable of so, so, so much more, like chaining effects and triggering them on condition. Plus, there are cases where we need to cleanup after an effect has run—like subscribing to an external resource—to prevent memory leaks. Totally worth running through the detailed explanation of effects with cleanup in the React documentation.
Context and useContext()
Context in React makes it possible to pass props down from a parent component to a child component. This saves you from the hassle of prop drilling. However, you could only make use of context in class components, but now you can make use of context in functional components using useContext() . Let’s create a counter example, we will pass the state and functions which will be used to increase or decrease the count from the parent component to child component using useContext(). First, let’s create our context:
const CountContext = React.createContext();
We’ll declare the count state and increase/decrease methods of our counter in our App component and set up the wrapper that will hold the component. We’ll put the context hook to use in the actual counter component in just a bit.
const App = () => {
// Use `setState()` to define a count variable and its state
const [count, setCount] = useState(0);
// Construct a method that increases the current `setCount` variable state by 1 with each click
const increase = () => {
setCount(count + 1);
};
// Construct a method that decreases the current `setCount` variable state by 1 with each click.
const decrease = () => {
setCount(count - 1);
};
// Create a wrapper for the counter component that contains the provider that will supply the context value.
return (
<div>
<CountContext.Provider
// The value is takes the count value and updates when either the increase or decrease methods are triggered.
value={{ count, increase, decrease }}
>
// Call the Counter component we will create next
<Counter />
</CountContext.Provider>
</div>
);
};
Alright, onto the Counter component! useContext() accepts an object (we’re passing in the CountContext provider) and allows us to tell React exactly what value we want (`count) and what methods trigger updated values (increase and decrease). Then, of course, we’ll round things out by rendering the component, which is called by the App.
We’ve merely scratched the surface of what React hooks are capable of doing, but hopefully this gives you a solid foundation. For example, there are even more advanced hooks that are available in addition to the basic ones we covered in this post. Here’s a list of those hooks with the descriptions offered by the documentation so you can level up now that you’re equipped with the basics:
Hook
Description
userReducer()
An alternative to useState. Accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method.
useCallback()
Returns a memoized callback. Pass an inline callback and an array of inputs. useCallback will return a memoized version of the callback that only changes if one of the inputs has changed.
useMemo()
Returns a memoized value. Pass a “create” function and an array of inputs. useMemo will only recompute the memoized value when one of the inputs has changed.
useRef()
useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
useImperativeMethods
useImperativeMethods customizes the instance value that is exposed to parent components when using ref. As always, imperative code using refs should be avoided in most cases. useImperativeMethods should be used with forwardRef.
useLayoutEffect
The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.
This little site by Remy Sharp’s makes it clear whether or not a JavaScript method changes the original array (aka mutates) or not.
I was actually bitten by this the other day. I needed the last element from an array, so I remembered .pop() and used it.
const arr = ["doe", "ray", "mee"];
const last = arr.pop();
// mee, but array is now ["doe", "ray"]
This certainly worked great right away, but I didn’t realize the original array had changed and it caused a problem. Instead, I had to find the non-mutating alternative:
const arr = ["doe", "ray", "mee"];
const last = arr.slice(-1);
// mee, arr is unchanged
I am attracted to the idea that you shouldn’t care how the code you author ends up in the browser. It’s already minified. It’s already gzipped. It’s already transmogrified (real word!) by things that polyfill it, things that convert it into code that older browsers understand, things that make it run faster, things that strip away unused bits, and things that break it into chunks by technology far above my head.
The trend is that the code we author is farther and farther away from the code we write, and like I said, I’m attracted to that idea because generally, the purpose of that is to make websites faster for users.
But as Dave notes, when something goes wrong…
As toolchains grow and become more complex, unless you are expertly familiar with them, it’s very unclear what transformations are happening in our code. Tracking the differences between the input and output and the processes that code underwent can be overwhelming. When there’s a problem, it’s increasingly difficult to hop into the assembly line and diagnose the issue and often there’s not an precise fix.