diff --git a/book/CH00_Introduction.adoc b/book/CH00_Introduction.adoc
index 0e28ba7..40468ee 100644
--- a/book/CH00_Introduction.adoc
+++ b/book/CH00_Introduction.adoc
@@ -2,8 +2,8 @@
= Introduction
:chapter: 00
:part: Hypermedia Concepts
-:part_url: ./part/hypermedia-concepts/
-:url: ./introduction/
+:part_url: /part/hypermedia-concepts/
+:url: /introduction/
This is a book about building applications using hypermedia systems. _Hypermedia systems_ might seem like a strange phrase:
how is hypermedia a _system_? Isn't hypermedia just a way to link documents together?
@@ -70,7 +70,8 @@ It is important to understand that, in his dissertation, Fielding was describing
late 1990s. The web, at that point, was simply web browsers exchanging hypermedia. That system, with its simple links
and forms, was what Fielding was calling RESTful.
-JSON APIs were a decade away from becoming a common tool in web development: REST was about _hypermedia_ and _the Web 1.0_.
+JSON APIs were a decade away from becoming a common tool in web development: REST was about _hypermedia_ and the 1.0
+version of The Web.
== Hypermedia-Driven Applications
@@ -147,16 +148,31 @@ ____
-[.design-note]
-.HTML Notes: Why Effective HTML?
+[.html-note]
+.HTML Notes: Hypermedia In Practice
****
-At the end of each chapter you will find tips and best practices for writing effective HTML.
+At the end of each chapter you will find tips and best practices for writing HTML well.
-It's very easy (and sometimes acceptable) to produce mediocre HTML that _seems to_ work,
-and many websites settle with _seeming to_ work.
+It's very easy (and sometimes acceptable) to produce mediocre HTML that, within a purview limited to one particular application, works -- this seems to be enough for most websites.
+But our websites, like men, are not islands.
+That is, they are not applications of a _platform_,
+but constituents of a _system_.
+In a systems view of the web, the purpose of writing HTML is not just to develop a particular application, but also to play along with other members of the Web.
+Thankfully for us hypermedia advocates, a few components, most prominently search engines and assistive technologies, have enough sway to keep people caring about HTML.
+Less fortunately, lack of awareness around hypermedia means that these components are seen as annoyances to get out of the way, demons to appease, or worse, legacy leftovers to ignore.
+
+After all, web development is so much easier without all this Web stuff.
+
+So why resist the tide? Why shouldn't we discard hypermedia and rewrite the web into the application platform it can clearly be?
+That's what the rest of this book will try to answer, in a practical, non theory-addled way.
+And at the ends of chapters, these HTML Notes will connect the concepts of hypermedia we discuss and the code samples we present to day-to-day web development.
+
+The executive summary:
+Well-written HTML is easier to read and debug, more accessible to all, ranked higher by search engines (not out of bias, but because they have an easier time scraping it).
+
+An important caveat:
+The mantra that HTML is "accessible by default" is misleading and shunning other technologies like JavaScript is misguided.
+Doing everything with "pure", "semantic" HTML is not a panacea, and testing is the ultimate indicator of quality over spec adherence.
But writing good, spec-compliant HTML lets browsers do a bunch of work for you. Furthermore, even when they don't, it makes it easier to write scripts that do. Fewer issues will be found during testing and you can release faster. When issues do come up, you can often fix them more easily by refactoring HTML as opposed to heaping JavaScript and ARIA attributes over everything.
-
-// TODO: check last sentence here; pulled together from various paragraphs
-Effective HTML typically loads faster, is easier to read and debug, performs better both with search engine ranking and screen reader accessibility, and can be scraped programatically.
****
\ No newline at end of file
diff --git a/book/CH01_HypermediaAReintroduction.adoc b/book/CH01_HypermediaAReintroduction.adoc
index fb5a8ab..248409f 100644
--- a/book/CH01_HypermediaAReintroduction.adoc
+++ b/book/CH01_HypermediaAReintroduction.adoc
@@ -1,7 +1,7 @@
= Hypermedia: A Reintroduction
:chapter: 01
-:url: ./hypermedia-reintroduction/
+:url: /hypermedia-reintroduction/
Hypermedia is a universal technology today, almost as common as electricity.
@@ -290,7 +290,7 @@ issuing an "`Asynchronous JavaScript and XML,`" or AJAX request, available in al
----
<1> Issue the request.
@@ -351,7 +351,7 @@ It needs to know:
In short, the logic in `updateUI()` needs to have intimate knowledge of the API endpoint at `/api/v1/contact/1`, knowledge provided
via some side-channel beyond the response itself. As a result, the `updateUI()` code and the
API have a strong relationship, known as _tight coupling_: if the format of the JSON response changes, then the code for `updateUI()` will almost certainly
-also need to be changed.
+also need to be changed as well.
==== Single Page Applications
@@ -376,8 +376,8 @@ are updated via JavaScript code and the framework then "`reacts`" to these chang
When the user interface is updated by a user these changes also flow _into_ the model objects, establishing a "`two-way`"
binding mechanism: the model can update the UI, and the UI can update the model.
-This is all very sophisticated and, today, very popular. But the fact is that developers that adopt this approach to building
-web applications have largely abandoned the web's underlying hypermedia system.
+This is all very sophisticated and, today, very popular. However, web developers that adopt this approach to building
+their web applications are abandoning the web's underlying hypermedia system.
HTML is still used to build user interfaces, but the _hypermedia_ aspect of the two major hypermedia controls,
anchors and forms, are ignored. Neither tag interacts with a server via their native _hypermedia_ mechanism. Rather,
@@ -388,8 +388,8 @@ So, as with our simple button above, the Single Page Application approach is _no
It does not take advantage of the existing RESTful architecture of the web, nor does it utilize the built-in functionality
found in HTML's native hypermedia controls.
-SPAs are somewhat like _thick client applications_ like the client-server applications of the
-1980s -- an architecture popular _before_ the web came along.
+SPAs are more much like _thick client applications_, that is, like the client-server applications of the
+1980s -- an architecture popular _before_ the web came along and that the web was, in many ways, a reaction to.
This approach _isn't necessarily wrong_, but it is worth thinking about _why_ web developers so frequently take it and
if there are reasons _not_ to go down this path.
@@ -408,24 +408,25 @@ This idea has really swept the internet. It started with a few major popular web
marketing sites and blogs.
____
-The JavaScript-based Single Page Application approach has taken the web development world by storm, and there was one
-major and very good reason for its success: The Single Page Application offers a far more interactive and immersive experience
-than the old, gronky, Web 1.0 hypermedia-based applications could. It had the ability to smoothly update elements inline on
-a page without a dramatic reload of the entire document, the ability to use CSS transitions to create nice visual effects,
-the ability to hook into arbitrary events like mouse movements. All of these gave JavaScript-based applications a huge advantage
-in building sophisticated user experiences.
+The JavaScript-based Single Page Application approach has taken the web development world by storm, and if there was one
+major for its wild success it was this: The Single Page Application offers a far more interactive and immersive experience
+than the old, gronky, Web 1.0 hypermedia-based applications could. SPAs had the ability to smoothly update elements inline on
+a page without a dramatic reload of the entire document, they had the ability to use CSS transitions to create nice visual effects,
+and the ability to hook into arbitrary events like mouse movements.
-So why on earth would you abandon this popular and modern approach for an older and much less discussed
-approach such as hypermedia?
+All of these gave JavaScript-based applications a huge advantage in building sophisticated user experiences.
+
+So, given this success, why on earth would you set aside this popular and modern approach to consider an older and
+less popular approach like hypermedia?
=== JavaScript Fatigue
-Well, we are glad you asked.
+We are glad you asked!
It turns out that the hypermedia architecture, even in its original Web 1.0 form, has a number of advantages when compared with
-the Single Page Application + JSON Data API approach:
+the Single Page Application + JSON Data API approach. Three of the biggest are:
-* It is an extremely simple approach to building web applications.
+* It is an extremely _simple_ approach to building web applications.
* It is extremely tolerant of content and API changes. In fact, it thrives on them!
@@ -438,15 +439,17 @@ The first two advantages, in particular, address major pain points in modern web
* JSON API churn -- constant changes made to JSON APIs to support application needs -- has become a major pain point for
many application teams.
-The combination of these two problems, along with other issues such as JavaScript library churn, has led to a phenomenon known as "`JavaScript Fatigue.`" This refers to a general sense of exhaustion with all the hoops that are necessary to jump through to
-get anything done in modern-day web applications.
+The combination of these two problems, along with other issues such as JavaScript library churn, has led to a phenomenon
+known as "`JavaScript Fatigue.`" This refers to a general sense of exhaustion with all the hoops that are necessary to
+jump through to get anything done in modern-day web applications.
-We believe that a hypermedia architecture can help cure JavaScript Fatigue for many developers and teams. But if hypermedia is so great, and if it addresses so many of the problems that beset the web
-development industry, why was it abandoned in the first place? After all, hypermedia was there first.
+We believe that a hypermedia architecture can help cure JavaScript Fatigue for many developers and teams.
-Why didn't web developers just stick with it?
+But if hypermedia is so great, and if it addresses so many of the problems that beset the web
+development industry, why was it abandoned in the first place? After all, hypermedia was there first. Why didn't web
+developers just stick with it?
-We believe that hypermedia hasn't made a comeback yet for two reasons.
+There are two major reasons hypermedia hasn't made a comeback in web development.
The first is this: the expressiveness of HTML _as a hypermedia_ hasn't changed much, if at all, since HTML 2.0, which
was released _in the mid 1990s_. Many new _features_ have been added to HTML, of course, but there haven't been _any_
@@ -460,7 +463,8 @@ HTML-as-hypermedia has fallen on hard times: as the interactivity and expressive
demands of web users have continued to increase, calling for more and more interactive web applications.
JavaScript-based applications coupled to data-oriented JSON APIs have stepped in as a way to provide these more
-sophisticated user interfaces. It was the _user experience_ that you could achieve in JavaScript, and that you couldn't achieve in plain HTML, that drove the web development community to the JavaScript-based
+sophisticated user interfaces. It was the _user experience_ that you could achieve in JavaScript, and that you couldn't
+achieve in plain HTML, that drove the web development community to the JavaScript-based
Single Page Application approach. The shift was not driven by any inherent superiority of the Single Page Application as a system
architecture.
@@ -474,9 +478,9 @@ understandable move to a more familiar model for building rich applications.
Not everyone abandoned hypermedia, of course. There have been heroic efforts to continue to advance hypermedia outside of
HTML, efforts like HyTime, VoiceXML, and HAL.
-But HTML, the most widely used hypermedia in the world, stopped making progress as a hypermedia. The web development
-world moved on, solving the interactivity problems with HTML and adopting a completely different
-system architecture along the way.
+But HTML, the most widely used hypermedia in the world, mostly stopped making progress as a hypermedia. The web development
+world moved on, solving the interactivity problems with HTML by adopting JavaScript-based SPAs and, inadvertently,
+a completely different system architecture.
== A Hypermedia Resurgence?
@@ -504,14 +508,16 @@ links and forms located on multiple web pages, submitting HTTP requests and gett
MPA applications, by their nature, are Hypermedia-Driven Applications: after all, they are exactly what Roy Fielding
was describing in his dissertation.
-These applications tend to be clunky, but they work reasonably well. Many web developers and teams choose to accept the limitations of plain HTML in the interest of simplicity and reliability.
+These applications tend to be clunky, but they work reasonably well. Many web developers and teams choose to accept the
+limitations of plain HTML in the interest of simplicity and reliability.
Rich Harris, creator of Svelte.js, a popular SPA library, and a thought-leader on the SPA side of the debate, has proposed a mix
of this older MPA style and the newer SPA style. Harris calls this approach to building web applications "`transitional,`" in that
it attempts to blend the MPA approach and the newer SPA approach into a coherent whole. (This is somewhat
similar to the "`transitional`" trend in architecture, which combines traditional and modern architectural styles.)
-"`Transitional`" is a fitting term for mixed-style applications, and it offers a reasonable compromise between the two approaches, using either one as appropriate on a case-by-case basis.
+"`Transitional`" is a fitting term for mixed-style applications, and it offers a reasonable compromise between the two
+approaches, using either one as appropriate on a case-by-case basis.
But this compromise still feels unsatisfactory.
@@ -523,7 +529,7 @@ of a "`transitional`" application -- for a particular feature.
It turns out that by adopting a hypermedia-oriented library, the interactivity gap between the MPA and the SPA approach
closes dramatically. You can use the MPA approach, that is, the hypermedia approach, for much more of your application
-without compromising your user interface. You might even be able to use the hypermedia approach for all your application
+without compromising your user interface. You might even be able to use the hypermedia approach for _all_ your application
needs.
Rather than having an SPA with a bit of hypermedia around the edges, or some mix of the two approaches, you can often create
@@ -535,7 +541,7 @@ software. While there are still times and places for the more complex SPA appro
by adopting a hypermedia-first approach and using a hypermedia-oriented library to push HTML as far as possible,
your web application can be powerful, interactive _and_ simple.
-One such hypermedia oriented library is https://htmx.org[htmx]. Htmx will be the focus of Part Two.
+One such hypermedia oriented library is https://htmx.org[htmx]. Htmx will be the focus of Part Two of this book.
We show that you can, in fact, create many common "`modern`" UI features found in sophisticated Single
Page Applications by instead using the hypermedia model.
@@ -575,7 +581,7 @@ Let's look at an htmx-powered implementation of the simple JavaScript-powered bu
<1> issues a `GET` request to `/contacts/1`, replacing the `contact-ui`.
As with the JavaScript powered button, this button has been annotated with some attributes. However, in
-this case we do not have any JavaScript scripting.
+this case we do not have any (explicit) JavaScript scripting.
Instead, we have _declarative_ attributes much like the `href` attribute on anchor tags and the `action` attribute on
form tags. The `hx-get` attribute tells htmx: "`When the user clicks this button, issue a `GET` request to `/contacts/1`.`"
@@ -586,7 +592,24 @@ Here we get to the crux of htmx and how it allows you to build Hypermedia-Driven
_The HTTP response from the server is expected to be in HTML format, not JSON_.
-This htmx-powered button is exchanging _hypermedia_ with the server, just like an anchor tag or form
+An HTTP response to this htmx-driven request might look something like this:
+
+.JSON
+[source,html]
+----
+
+
+
+----
+
+This small bit of HTML would be placed into the element in the DOM with the id `contact-ui`.
+
+Thus, this htmx-powered button is exchanging _hypermedia_ with the server, just like an anchor tag or form
might, and thus the interaction is still within the original hypermedia model of the web. Htmx _is_ adding functionality
to this button (via JavaScript), but that functionality is _augmenting_ HTML as a hypermedia. Htmx extends the hypermedia
system of the web, rather than _replacing_ that hypermedia system with a totally different architecture.
@@ -661,7 +684,7 @@ Any software project has a complexity budget, explicit or not: there is only so
team can tolerate and every new feature and implementation choice adds at least a bit more to the overall complexity
of the system.
-What is particularly nasty about complexity is that it appears to grow exponentially: one day you can keep the entire
+What is particularly nasty about complexity is that it tends to grow exponentially: one day you can keep the entire
system in your head and understand the ramifications of a particular change, and a week later the whole system seems
intractable. Even worse, efforts to help control complexity, such as introducing abstractions or infrastructure to
manage the complexity, often end up making things even more complex. Truly, the job of the good software engineer
@@ -695,20 +718,3 @@ We hope that, in addition, you will also become as passionate about it as we are
This book is, in part, a plea that we "`let the web be the web`", that we take the original architecture of the web
seriously, and that we consider the entire _hypermedia system_ it makes available to us when we build applications
with it.
-
-
-[.design-note]
-.HTML Note: Stay Close to the Output
-****
-[quote, Manuel Matuzović, 'https://www.matuzo.at/blog/2023/single-page-applications-criticism[Why I\'m not the biggest fan of Single Page Applications]']
-The fact that the HTML document is something that you barely touch, because everything you need in there will be injected via JavaScript, puts the document and the page structure out of focus.
-
-In order to avoid `
` soup (or Markdown soup, or Component soup), you need to be aware of the markup you're producing and be able to change it.
-
-Some SPA frameworks, and some web components, make this more difficult by putting layers of abstraction between the code the developer writes and the generated markup.
-
-While these abstractions can allow developers to create richer UI or work faster,
-their pervasiveness means that developers can lose sight of the actual HTML (and JavaScript) being sent to clients.
-Without diligent testing, this leads to inaccessibility, poor SEO, and bloat.
-****
-
diff --git a/book/CH02_ComponentsOfAHypermediaSystem.adoc b/book/CH02_ComponentsOfAHypermediaSystem.adoc
index c9180a1..7bdc784 100644
--- a/book/CH02_ComponentsOfAHypermediaSystem.adoc
+++ b/book/CH02_ComponentsOfAHypermediaSystem.adoc
@@ -1,7 +1,7 @@
= Components Of A Hypermedia System
:chapter: 02
-:url: ./hypermedia-components/
+:url: /hypermedia-components/
A _hypermedia system_ consists of a number of components, including:
@@ -53,14 +53,14 @@ A typical URL might look like this:
.A simple URL
----
-https://hypermedia.systems/book
+https://hypermedia.systems/book/contents/
----
This particular URL is made up of the following components:
* A protocol or scheme (in this case, `https`)
* A domain (e.g., `hypermedia.systems`)
-* A path (e.g., `/book`)
+* A path (e.g., `/book/contents`)
This URL uniquely identifies a retrievable _resource_ on the internet, to which an _HTTP Request_ can be issued by
a hypermedia client that "`speaks`" HTTPS, such as a web browser. If this URL is found as the reference of a
@@ -85,7 +85,7 @@ would be `https://hypermedia.systems/book/contents/`.
=== Hypermedia Protocols
The hypermedia control (link) above tells a browser: "`When a user clicks on this text, issue a request to
-https://hypermedia.systems/book/contents/ using the Hypertext Transfer Protocol,`" or HTTP.
+`https://hypermedia.systems/book/contents/` using the Hypertext Transfer Protocol,`" or HTTP.
HTTP is the _protocol_ used to transfer HTML (hypermedia) between browsers (hypermedia clients) and servers (hypermedia
servers) and, as such, is the key network technology that binds the distributed hypermedia system of the web together.
@@ -175,7 +175,8 @@ These methods _roughly_ line up with the "`Create/Read/Update/Delete`" or CRUD p
.Put vs. Post
****
-While HTTP Actions correspond roughly to CRUD, they are not the same. The technical specfications for these methods make no such connection, and are often somewhat difficult to read. Here, for example, is the documentation
+While HTTP Actions correspond roughly to CRUD, they are not the same. The technical specifications for these methods make
+no such connection, and are often somewhat difficult to read. Here, for example, is the documentation
on the distinction between a `POST` and a `PUT` from https://www.rfc-editor.org/rfc/rfc2616[RFC-2616].
[quote, RFC-2616, https://www.rfc-editor.org/rfc/rfc2616#section-9.6]
@@ -185,14 +186,15 @@ resource's own semantics, whereas the enclosed representation in a PUT request i
target resource. Hence, the intent of PUT is idempotent and visible to intermediaries, even though the exact
effect is only known by the origin server.
____
-So, in plain terms, a `POST` can be handled by a server pretty much however it likes, whereas a `PUT` should be handled
-as a "`replacement`" of the resource, although the language, once again allows the server to do pretty much whatever it
-would like within the constraint of being https://developer.mozilla.org/en-US/docs/Glossary/Idempotent[_idempotent_].
+In plain terms, a `POST` can be handled by a server pretty much however it likes, whereas a `PUT` should be handled
+as a "`replacement`" of the resource, although the language, once again allows the server to do pretty much whatever it
+would like within the constraint of being https://developer.mozilla.org/en-US/docs/Glossary/Idempotent[_idempotent_].
****
In a properly structured HTML-based hypermedia system you would use an appropriate HTTP method for the operation a
-particular hypermedia control performs. For example, if a hypermedia control such as a button _deletes_ a resource, ideally it should issue an HTTP `DELETE` request to do so.
+particular hypermedia control performs. For example, if a hypermedia control such as a button _deletes_ a resource,
+ideally it should issue an HTTP `DELETE` request to do so.
A strange thing about HTML, though, is that the native hypermedia controls can only issue HTTP `GET` and `POST` requests.
@@ -201,7 +203,9 @@ Anchor tags always issue a `GET` request.
Forms can issue either a `GET` or `POST` using the `method` attribute.
Despite the fact that HTML -- the world's most popular hypermedia -- has been designed alongside
-HTTP (which is the Hypertext Transfer Protocol, after all!): if you wish to issue `PUT`, `PATCH` or `DELETE` requests you currently _have to_ resort to JavaScript to do so. Since a `POST` can do almost anything, it ends up being used for any mutation on the server, and `PUT`, `PATCH` and `DELETE` are left aside in plain HTML-based
+HTTP (which is the Hypertext Transfer Protocol, after all!): if you wish to issue `PUT`, `PATCH` or `DELETE` requests
+you currently _have to_ resort to JavaScript to do so. Since a `POST` can do almost anything, it ends up being used for
+any mutation on the server, and `PUT`, `PATCH` and `DELETE` are left aside in plain HTML-based
applications.
This is an obvious shortcoming of HTML as a hypermedia; it would be wonderful to see this fixed in the
@@ -268,12 +272,13 @@ Here are some of the more common or interesting ones:
There are some fairly subtle differences between HTTP response codes (and, to be honest, some ambiguities between them).
The difference between a `302` redirect and a `303` redirect, for example, is that the former will issue the request to the
-new URL using the same HTTP method, whereas the latter will always use a `GET`. A small, but often crucial difference,
-as we will see later in the book.
+new URL using the same HTTP method as the initial request, whereas the latter will always use a `GET`. This is a small
+but often crucial difference, as we will see later in the book.
-Nonetheless, a well crafted hypermedia system will take advantage of both HTTP methods and HTTP response codes to create a sensible
-hypermedia API. You do not want to build a hypermedia system that uses a `POST` method for all requests and responds
-with `200 OK` for every response. Some JSON Data APIs built on top of HTTP do exactly this!
+A well crafted Hypermedia-Driven Application will take advantage of both HTTP methods and HTTP response codes to create
+a sensible hypermedia API. You do not want to build a Hypermedia-Driven Application that uses a `POST` method for all
+requests and responds with `200 OK` for every response, for example. (Some JSON Data APIs built on top of HTTP do exactly
+this!)
When building a Hypermedia-Driven Application, you want, instead, to go "`with the grain`" of the web and use HTTP methods
and response codes as they were designed to be used.
@@ -291,13 +296,15 @@ another HTTP request for that resource until that time limit has expired.
Another important caching-related response header is `Vary`. This response header can be used to indicate exactly what
headers in an HTTP Request form the unique identifier for a cached result. This becomes important to allow the browser
-to correctly cache content in situations where a particular header affects the form of the server response. A common
-pattern in htmx-powered applications, for example, is to use a custom header set by htmx, `HX-Request`, to differentiate between
-"`normal`" web requests and requests submitted by htmx. To properly cache the response to these requests, the `HX-Request`
-request header must be indicated by the `Vary` response header.
+to correctly cache content in situations where a particular header affects the form of the server response.
+
+A common pattern in htmx-powered applications, for example, is to use a custom header set by htmx, `HX-Request`, to
+differentiate between "`normal`" web requests and requests submitted by htmx. To properly cache the response to these
+requests, the `HX-Request` request header must be indicated by the `Vary` response header.
A full discussion of caching HTTP responses is beyond the scope of this chapter; see
-the https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching[MDN Article on HTTP Caching] if you would like to know more on the topic.
+the https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching[MDN Article on HTTP Caching] if you would like to know more
+on the topic.
=== Hypermedia Servers
@@ -305,17 +312,17 @@ Hypermedia servers are any server that can respond to an HTTP request with an HT
this means that nearly any programming language can be used to build a hypermedia server. There are a vast number of
libraries available for building HTTP-based hypermedia servers in nearly every programming language imaginable.
-This is one of the best aspects of adopting hypermedia as your primary technology for building a web application: it removes
-the pressure of adopting JavaScript as a backend technology. In contrast, if you decide to adopt a JavaScript-heavy
-Single Page Application-based front end, and you use JSON Data APIs, you will feel significant pressure to adopt
-JavaScript on the back end.
+This turns out to be one of the best aspects of adopting hypermedia as your primary technology for building a web application: it removes
+the pressure of adopting JavaScript as a backend technology. If you use a JavaScript-heavy Single Page Application-based
+front end, and you use JSON Data APIs, you are going to feel significant pressure to adopt JavaScript on the back end as
+well.
In this latter situation, you already have a ton of code written in JavaScript. Why maintain two separate code bases in
two different languages? Why not create reusable domain logic on the client-side as well as the server-side? Now that
JavaScript has excellent server-side technologies available like Node and Deno, why not just use a single language for
everything?
-In contrast, using a hypermedia-based front end gives you a lot more freedom in picking the back end technology you want
+In contrast, building a Hypermedia-Driven Application gives you a lot more freedom in picking the back end technology you want
to use. Your decision can be based on the domain of your application, what languages and server software you are familiar
with or are passionate about, or just what you feel like trying out.
@@ -368,7 +375,8 @@ to hang together. Without a sophisticated client that can do this, hypermedia c
much less useful.
This is one reason why JSON APIs have rarely adopted hypermedia controls successfully: JSON APIs are typically consumed
-by code that is expecting a fixed format and isn't designed to be a hypermedia client. For clients like this, the
+by code that is expecting a fixed format and that isn't designed to be a hypermedia client. This is totally understandable:
+building a good hypermedia client is hard! For JSON API clients like this, the
power of hypermedia controls embedded within an API response is irrelevant and often simply annoying:
[quote, Freddie Karlbom,https://techblog.commercetools.com/graphql-and-rest-level-3-hateoas-70904ff1f9cf]
@@ -378,7 +386,7 @@ after almost 20 years, HATEOAS still hasn’t gained wide adoption among develop
like wildfire because it solves real-world problems.
____
-HATEOAS will be described in more detail below, but the take away here is that a good hypermedia client is a necessary
+HATEOAS will be described in more detail below, but the takeaway here is that a good hypermedia client is a necessary
component within a larger hypermedia system.
== REST
@@ -394,27 +402,28 @@ perspective: Section 5.1. This section contains the core concepts (Fielding call
State Transfer, or REST.
Before we get into the muck, however, it is important to understand that Fielding discusses REST as a _network architecture_,
-that is an entirely different way of architecting a distributed system. And a novel one that should be _contrasted_ with
-earlier distributed systems.
+that is, as an entirely different way of architecting a distributed system. And, further, as a novel network
+architecture that should be _contrasted_ with earlier approaches to distributed systems.
It is also important to emphasize that, at the time Fielding wrote his dissertation, JSON APIs and AJAX did not exist.
He was describing the early web, with HTML being transferred over HTTP by early browsers, as a hypermedia system.
Today, in a strange turn of events, the term "`REST`" is mainly associated with JSON Data APIs, rather than with HTML
-and hypermedia. This becomes extremely humorous once you realize that the vast majority of JSON Data APIs aren't
-RESTful, and, in fact _can't_ be RESTful, since they aren't using a natural hypermedia format.
+and hypermedia. This is extremely funny once you realize that the vast majority of JSON Data APIs aren't
+RESTful, in the original sense, and, in fact, _can't_ be RESTful, since they aren't using a natural hypermedia format.
-To re-emphasize: REST, as coined by Fielding, describes _the pre-JSON API web_, and letting go of the current, common
-usage of the term as "`JSON API`" is necessary to develop a proper understanding of it.
+To re-emphasize: REST, as coined by Fielding, describes _the pre-API web_, and letting go of the current, common
+usage of the term REST to simply mean "`a JSON API`" is necessary to develop a proper understanding of the idea.
=== The "`Constraints`" of REST
-Fielding defines various "`constraints`" to describe how a RESTful system must behave. This approach
+In his dissertation, Fielding defines various "`constraints`" to describe how a RESTful system must behave. This approach
can feel a little round-about and difficult to follow for many people, but it is an appropriate approach for an academic
-dissertation. Given a bit of time thinking about the constraints he outlines, and some concrete examples, it will
-become easy to assess whether a given system actually satisfies the architectural requirements of REST or not.
+document. Given a bit of time thinking about the constraints he outlines and some concrete examples of those
+constraints it will become easy to assess whether a given system actually satisfies the architectural requirements of
+REST or not.
-Here are the constraints of REST, as outlined in Fielding's dissertation:
+Here are the constraints of REST Fielding outlines:
* It is a client-server architecture (section 5.1.2).
* It must be stateless; (section 5.1.3) that is, every request contains all information necessary to respond to that request.
@@ -454,11 +463,10 @@ This session information is typically stored in some sort of shared storage acro
like the current user's email or id, their roles, partially created domain objects, caches, and so forth.
This violation of the Statelessness REST architectural constraint has proven to be useful for building web applications
-and does not appear to have had a significant impact on the overall flexibility of the approach. But
-bear in mind that even Web 1.0 applications often violate the purity of REST in the interest of pragmatic
-trade-offs.
+and does not appear to have had a major impact on the overall flexibility the web. But it is worth bearing in mind that
+even Web 1.0 applications often violate the purity of REST in the interest of pragmatic trade-offs.
-Note, however, that sessions do cause additional operational complexity headaches when deploying hypermedia
+And it must be said that sessions _do_ cause additional operational complexity headaches when deploying hypermedia
servers; these may need shared access to session state information stored across an entire cluster. So
Fielding was correct in pointing out that an ideal RESTful system, one that did not violate this constraint, would be simpler and therefore more robust.
@@ -476,7 +484,8 @@ easy to see how this constraint is satisfied by the web.
=== The Uniform Interface Constraint
-Now we come to the most interesting and, in our opinion, innovative constraint in REST: that of the _uniform interface_.
+Now we come to the most interesting and, in our opinion, most innovative constraint in REST: that of the _uniform interface_.
+
This constraint is the source of much of the _flexibility_ and _simplicity_ of a hypermedia system, so we are going to
spend some time on it.
@@ -522,14 +531,15 @@ the Uniform Interface, of REST and why hypermedia provides such a powerful syste
The Self-Descriptive Messages constraint requires that, in a RESTful system, messages must be _self-describing_.
This means that _all information_ necessary to both display _and also operate_ on the data being represented must be
-present in the response. In a properly RESTful system, there can be no additional "`side`" information necessary for a client to transform a response from a server into a useful user interface. Everything must "`be in`" the message itself,
+present in the response. In a properly RESTful system, there can be no additional "`side`" information necessary for a
+client to transform a response from a server into a useful user interface. Everything must "`be in`" the message itself,
in the form of hypermedia controls.
-This might sound a little abstract, let's look at a concrete example.
+This might sound a little abstract so let's look at a concrete example.
Consider two different potential responses from an HTTP server for the URL `\https://example.com/contacts/42`.
-Both responses will return information about a contact, but they will take very different forms.
+Both responses will return information about a contact, but each response will take very different forms.
The first implementation returns an HTML representation:
@@ -577,7 +587,7 @@ So REST _trades off_ representational efficiency for other goals.
To understand these other goals, first notice that the HTML representation has a hyperlink in it to navigate to a page
to archive the contact. The JSON representation, in contrast, does not have this link.
-What are the ramifications of this fact for a client of the JSON API?
+What are the ramifications of this fact for a _client_ of the JSON API?
What this means is that the JSON API client must know _in advance_ exactly what other URLs (and request methods) are
available for working with the contact information. If the JSON client is able to update this contact in some way, it
@@ -585,20 +595,21 @@ must know how to do so from some source of information _external_ to the JSON me
status, say "`Archived`", does this change the allowable actions? If so, what are the new allowable actions?
The source of all this information might be API documentation, word of mouth or, if the developer controls both the server
-and the client, internal knowledge. But it is _outside_ the message.
+and the client, internal knowledge. But this information is implicit and _outside_ the response.
-The hypermedia (or HTML) client, on the other hand, needs only to know how to render the given HTML. It doesn't need to understand
-what actions are available for this contact: they are simply encoded _within_ the HTML itself as hypermedia controls. It doesn't need to
-understand what the status field means or, in fact, what a contact even is!
+Contrast this with the hypermedia (HTML) response. In this case, the hypermedia client (that is, the browser) needs
+only to know how to render the given HTML. It doesn't need to understand what actions are available for this contact:
+they are simply encoded _within_ the HTML response itself as hypermedia controls. It doesn't need to understand what
+the status field means. In fact, the client doesn't even know what a contact is!
The browser, our hypermedia client, simply renders the HTML and allows the user, who presumably understands the concept
of a Contact, to make a decision on what action to pursue from the actions made available in the representation.
This difference between the two responses demonstrates the crux of REST and hypermedia, what makes them so powerful
- and flexible: clients (that is, web browsers) don't need to understand _anything_ about the underlying resources being
+and flexible: clients (again, web browsers) don't need to understand _anything_ about the underlying resources being
represented.
-Browsers only (only! As if it is easy!) need to understand how to parse and display hypermedia, in this case HTML. This
+Browsers only (only! As if it is easy!) need to understand how to interpret and display hypermedia, in this case HTML. This
gives hypermedia-based systems unprecedented flexibility in dealing with changes to both the backing representations and
to the system itself.
@@ -651,7 +662,8 @@ representation, in a way that the JSON representation does not.
A client interpreting the JSON response must, again, understand not only the general concept of a Contact,
but also specifically what the "`status`" field with the value "`Archived`" means. It must know exactly what operations
-are available on an "`Archived`" contact, to appropriately display them to an end user. The state of the application is not encoded in the response, but rather conveyed through a mix of raw data and side channel information such as
+are available on an "`Archived`" contact, to appropriately display them to an end user. The state of the application is
+not encoded in the response, but rather conveyed through a mix of raw data and side channel information such as
API documentation.
Furthermore, in the majority of front end SPA frameworks today, this contact information would live _in memory_ in a
@@ -762,7 +774,8 @@ nonetheless.
=== An Optional Constraint: Code-On-Demand
We called The Layered System constraint the final "`required`" constraint because
-Fielding mentions one additional constraint on a RESTful system. This Code On Demand constraint is somewhat awkwardly described as "`optional`" (Section 5.1.7).
+Fielding mentions one additional constraint on a RESTful system. This Code On Demand constraint is somewhat awkwardly
+described as "`optional`" (Section 5.1.7).
In this section, Fielding says:
@@ -778,8 +791,9 @@ So, scripting was and is a native aspect of the original RESTful model of the we
should of course be allowed in a Hypermedia-Driven Application.
However, in a Hypermedia-Driven Application the presence of scripting should _not_ change the fundamental networking
-model: hypermedia should still be the engine of application state, server communication should still consist of
-hypermedia exchanges rather than, for example, JSON data exchanges, and so on. (JSON Data API's certainly have their place; in Chapter 10 we'll discuss when and how to use them).
+model: hypermedia should continue to be the engine of application state, server communication should still consist of
+hypermedia exchanges rather than, for example, JSON data exchanges, and so on. (JSON Data API's certainly have their
+place; in Chapter 10 we'll discuss when and how to use them).
Today, unfortunately, the scripting layer of the web, JavaScript, is quite often used to _replace_, rather than augment
the hypermedia model. We will elaborate in a later chapter what scripting that does not replace the underlying hypermedia
@@ -796,10 +810,13 @@ working in web development, and building a hypermedia-oriented library to boot,
special nature of HTML, hypermedia and the web!
-[.design-note]
-.HTML Note:
Soup
+[.html-note]
+.HTML Notes:
Soup
****
-The best-known kind of messy HTML is `
` soup.
+The best-known kind of messy HTML is `
` soup.
+
+Advances in CSS and JavaScript technology have mostly obviated the need to add extraneous "wrapper" elements to out documents.
+However, while the number of elements can fall, the quality of usage does not necessatily improve.
When developers fall back on the generic `
` and `` elements instead of more meaningful tags,
we either degrade the quality of our websites or create more work for ourselves -- probably both.
@@ -832,5 +849,16 @@ It's not obvious from the HTML source that this is a button,
making the source harder to read and the absence of these attributes harder to spot.
The source code of pages with div soup is difficult to edit and debug.
-To avoid div soup, learn the meaning of available tags and consider each another tool in your tool chest. (With the 113 elements currently defined in the spec, it's more of a tool shed).
+"`This is silly,`" you might be thinking.
+Who uses a div as a button?
+Ignoring the answer (more people than you'd think), not every UI pattern has a designated HTML element.
+We often need to compose elements and augment them with attributes.
+Do you know, off the top of your head, the best elements and attributes to use for...
+
+// TODO dzk (maybe give the correct elements here? I don't know them... :)
+* A "command palette" menu?
+* A play-pause button?
+* A search field with a search button next to it? (Check the HTML spec -- there might be things on there you don't remember from before!)
+
+To avoid div soup, learn the meaning of available tags and consider each another tool in your tool chest. (With the 113 elements currently defined in the spec, it's more of a whole shed).
****
\ No newline at end of file
diff --git a/book/CH03_BuildingASimpleWebApplication.adoc b/book/CH03_BuildingASimpleWebApplication.adoc
index 8563f3c..22d0624 100644
--- a/book/CH03_BuildingASimpleWebApplication.adoc
+++ b/book/CH03_BuildingASimpleWebApplication.adoc
@@ -1,17 +1,18 @@
= A Web 1.0 Application
:chapter: 03
-:url: ./a-web-1-0-application/
+:url: /a-web-1-0-application/
To start our journey into Hypermedia-Driven Applications, we are going to create a simple contact management web
application called Contact.app. We will start with a basic, "`Web 1.0-style`" Multi-Page Application (MPA), in the grand
-CRUD (Create, Read, Update, Delete) tradition. It will not be the best contact management application in the world; it will be simple and it will do its job.
+CRUD (Create, Read, Update, Delete) tradition. It will not be the best contact management application in the world, but
+it will be simple and it will do its job.
This application will also be easy to incrementally improve in the coming chapters by utilizing the hypermedia-oriented
library htmx.
By the time we are finished building and enhancing the application, over the next few chapters, it will have some very
-slick features that most developers today would assume requires the use of a heavy JavaScript framework.
+slick features that most developers today would assume requires the use of a SPA JavaScript framework.
== Picking A "`Web Stack`"
@@ -36,29 +37,31 @@ More importantly, Python is easy to read even if you aren't familiar with it.
We chose the Flask web framework because it is simple and does not impose a lot of structure on top of the
basics of HTTP request handling.
-This bare-bones approach is a good match for our needs: in other cases you might consider a more full-featured Python framework, such as https://www.djangoproject.com/[Django], which supplies much more functionality out of the box than Flask does.
+This bare-bones approach is a good match for our needs: in other cases you might consider a more full-featured Python
+framework, such as https://www.djangoproject.com/[Django], which supplies much more functionality out of the box than
+Flask does.
-By using Flask we are able
-to keep the book focused on _hypermedia
-exchanges_.
-
-So, even if this isn't your preferred stack, keep going: you will gain from the patterns we introduce here.
+By using Flask for our book, we will be able to keep our code focused on _hypermedia exchanges_.
We picked Jinja2 templates because they are the default templating language for Flask. They are simple enough and
similar enough to most other server-side templating languages that most people who are familiar with any server-side
(or client-side) templating library should be able to understand them quickly and easily.
+Even if this combination of technologies isn't your preferred stack, please, keep reading: you will learn quite a bit from
+the patterns we introduce in the coming chapters and it shouldn't be hard to map them into your preferred language and
+frameworks.
+
With this stack we will be rendering HTML _on the server-side_ to return to clients, rather than producing JSON. This
-is the traditional approach to building web applications, but, with the rise of SPAs, is not as widely used a technique
-as it once was. Today, as people are rediscovering this approach to building web applications, the term "`Server-Side
-Rendering`" or SSR is emerging as the way that people talk about this style of templating. This is in contrast with
+is the traditional approach to building web applications. However, with the rise of SPAs, this approach is not as
+widely used a technique as it once was. Today, as people are rediscovering this style of web applications, the term
+"`Server-Side Rendering`" or SSR is emerging as the way that people talk about it. This contrasted with
"`Client-Side Rendering`", that is, rendering templates in the browser with data retrieved in JSON form from the server,
as is common in SPA libraries.
In Contact.app we will intentionally keep things as simple as possible to maximize the teaching value of our code: it
-won't be perfectly factored code, but it will
-be easy to follow for readers even if they have little Python experience, and it should be easy to translate the application
-and the techniques demonstrated into your preferred programming language and web framework.
+won't be perfectly factored code, but it will be easy to follow for readers, even if they have little Python experience,
+and it should be easy to translate both the application and the techniques demonstrated into your preferred programming
+environment.
== Python
@@ -67,15 +70,15 @@ the various technologies we use _around_ that hypermedia. This has some obvious
with Python, for example, some example python code in the book may be a bit confusing or mysterious at first.
If you feel like you need a quick introduction to the language before diving into the code, we recommend the following
-books/websites:
+books and websites:
* https://nostarch.com/python-crash-course-3rd-edition[Python Crash Course] from No Starch Press
* https://learnpythonthehardway.org/python3/[Learn Python The Hard Way] by Zed Shaw
* https://www.py4e.com/[Python For Everybody] by Dr. Charles R. Severance
We think most web developers, even developers who are unfamiliar with Python, should be able to follow
-along. Most of the authors hadn't written much Python before writing this book, and we got the hang of
-it pretty quickly.
+along with our examples. Most of the authors of this book hadn't written much Python before writing it, and we got the
+hang of it pretty quickly.
== Introducing Flask: Our First Route
@@ -131,7 +134,7 @@ we are going to redirect to another path, the `/contacts` path. Redirects are a
redirect a client to another location with an HTTP response.
We are going to display a list of contacts as our root page, and, arguably, redirecting to the `/contacts` path to
-display this information is a bit more consistent with notion of resources with REST. This is a judgement call on our
+display this information is a bit more consistent with the notion of resources with REST. This is a judgement call on our
part, and not something we feel is too important, but it makes sense in terms of routes we will set up later in the
application.
@@ -407,8 +410,7 @@ of the `Contact` class in Python, if you aren't familiar with it.)
While the handler code for this route is very simple, the `new.html` template is more complicated.
****
-For the
-remaining templates we are going to omit the layout directive and the content block declaration, but you
+For the remaining templates we are going to omit the layout directive and the content block declaration, but you
can assume they are the same unless we say otherwise. This will let us focus on the "meat" of the template.
****
@@ -436,7 +438,7 @@ Here is what our HTML looks like:
In the first line of code we create a form that will submit back _to the same path_ that we are handling: `/contacts/new`.
Rather than issuing an HTTP `GET` to this path, however, we will issue an HTTP `POST` to it. Using a `POST` in this manner
-will signal to the server that we want to create a new Contact, rather than get a form.
+will signal to the server that we want to create a new Contact, rather than get a form for creating one.
We then have a label (always a good practice!) and an input that captures the email of
the contact being created. The name of the input is `email` and, when this form is submitted, the value of this input
@@ -478,12 +480,11 @@ Finally, we have a button that will submit the form, the end of the form tag, an
----
-Easy to miss in this straight-forward example: we are seeing the flexibility
-of hypermedia in action.
+It is easy to miss in this straight-forward example: we are seeing the flexibility of hypermedia in action.
If we add a new field, remove a field, or change the logic around how fields are validated or work with one another,
this new state of affairs would be reflected in the new hypermedia representation given to users. A user would see the
-updated new form, and be able to work with new features, with no software update required.
+updated new form and be able to work with these new features, with no software update required.
==== Handling the post to /contacts/new
@@ -856,20 +857,22 @@ Is it time to reach for a JavaScript framework and JSON APIs to make our contact
No. No it isn't.
-It turns out that we can improve the user experience of this application within the
-hypermedia architecture. In the next few chapters we will look at https://htmx.org[htmx], a hypermedia-oriented library
+It turns out that we can improve the user experience of this application while retaining its fundamental hypermedia
+architecture.
+
+In the next few chapters we will look at https://htmx.org[htmx], a hypermedia-oriented library
that will let us improve our contact application _without_ abandoning the hypermedia approach we have used so far.
-
[.design-note]
-.HTML Note: Semantic HTML
+.HTML Notes: Semantic HTML
****
+Telling people to "use semantic HTML" instead of "read the spec" has led to a lot of people guessing at the meaning of tags -- "`looks pretty semantic to me!" -- instead of engaging with the spec.
+
[quote,https://t-ravis.com/post/doc/semantic_the_8_letter_s-word/]
I think being asked to write _meaningful_ HTML better lights the path to realizing that it isn't about what the text means to humans--it's about using tags for the purpose outlined in the specs to meet the needs of software like browsers, assistive technologies, and search engines.
-Telling people to "use semantic HTML" instead of "read the spec" has led to a lot of people guessing at the meaning of tags -- "`looks pretty semantic to me!" -- instead of engaging with the spec.
-
We recommend talking about, and writing, _conformant_ HTML.
+(We can always bikeshed further).
Use the elements to the full extent provided by the HTML specification,
and let the software take from it whatever meaning they can.
****
diff --git a/book/CH04_ExtendingHTMLAsHypermedia.adoc b/book/CH04_ExtendingHTMLAsHypermedia.adoc
index f46b70c..ca5bd9e 100644
--- a/book/CH04_ExtendingHTMLAsHypermedia.adoc
+++ b/book/CH04_ExtendingHTMLAsHypermedia.adoc
@@ -2,8 +2,8 @@
= Extending HTML As Hypermedia
:chapter: 04
:part: Hypermedia-Driven Web Applications with Htmx
-:part_url: ./part/htmx/
-:url: ./extending-html-as-hypermedia/
+:part_url: /part/htmx/
+:url: /extending-html-as-hypermedia/
In the previous chapter we introduced a simple Web 1.0-style hypermedia application to manage contacts. Our application
supported the normal CRUD operations for contacts, as well as a simple mechanism for searching contacts. Our application
@@ -11,7 +11,8 @@ was built using nothing but forms and anchor tags, the traditional hypermedia co
The application exchanges hypermedia (HTML) with the server over HTTP, issuing `GET` and `POST` HTTP requests and
receiving back full HTML documents in response.
-It is a basic web application, but it is also definitely a Hypermedia-Driven Application. It is robust, it leverages the web's native technologies, and it is simple to understand.
+It is a basic web application, but it is also definitely a Hypermedia-Driven Application. It is robust, it leverages the
+web's native technologies, and it is simple to understand.
So what's not to like about the application?
@@ -33,7 +34,8 @@ cousins.
We could address this issue by adopting a Single Page Application framework, and updating our server-side to
provide JSON-based responses. Single Page Applications eliminate the clunkiness of web 1.0 applications by updating a
-web page directly: they mutate the Document Object Model (DOM) directly, without doing a full page refresh.
+web page without refreshing it: they can mutate parts of the Document Object Model (DOM) of the existing page without
+needing to replace (and re-render) the entire page.
.The DOM
****
@@ -55,19 +57,24 @@ with the application sacrificing the advantages of hypermedia in order to provid
Many web developers today would not even consider the hypermedia approach due to the perceived "`legacy`" feel of these
web 1.0 style applications.
-The second, technical point may strike you as a bit pedantic, and we are the first to admit that conversations around
-REST and which HTTP Action is right for a given operation can become very tedious. But still, it's odd that,
-when using plain HTML, it is impossible to use HTTP fully.
+Now, the second more technical issue we mentioned may strike you as a bit pedantic, and we are the first to admit that
+conversations around REST and which HTTP Action is right for a given operation can become very tedious. But still, it's
+odd that, when using plain HTML, it is impossible to use all the functionality of HTTP!
+
+Just seems wrong, doesn't it?
== A Close Look At A Hyperlink
-It turns out that we can boost the interactivity of our application without resorting to the SPA approach, by using one of several available hypermedia-oriented JavaScript libraries.
-We'll use the library that we've developed, https://htmx.org[htmx], not only because we know it inside and out, but because we built it purely to extend HTML as a hypermedia.
+It turns out that we can boost the interactivity of our application and address both of these issues _without_ resorting
+to the SPA approach. We can do so by using one of several available _hypermedia-oriented_ JavaScript libraries.
+In this book, naturally, we will use the library that we've developed, https://htmx.org[htmx]. We will use it not only
+because we know it inside and out, but also because we built it to extend HTML as a hypermedia and address the issues
+with legacy HTML applications we mentioned above (as well as few others.)
-To understand how htmx allows us to improve the UX of our Web 1.0 style
-application without abandoning hypermedia, let's revisit the hyperlink/anchor tag from Chapter 1. Recall, a hyperlink
-is what is known as a _hypermedia control_, a mechanism that describes some sort of interaction by encoding information about that interaction directly and completely within
-itself.
+Before we get into how htmx allows us to improve the UX of our Web 1.0 style application, let's revisit the
+hyperlink/anchor tag from Chapter 1. Recall, a hyperlink is what is known as a _hypermedia control_, a mechanism that
+describes some sort of interaction with a server by encoding information about that interaction directly and completely
+within the control itself.
Consider again this simple anchor tag which, when interpreted by a browser, creates a hyperlink to the website for
this book:
@@ -87,8 +94,8 @@ Let's break down exactly what happens with this link:
* The browser will issue an HTTP `GET` to `https://hypermedia.systems`...
* The browser will load the HTML body of the HTTP response into the browser window, replacing the current document.
-So we have four aspects of a simple hypermedia link like this, with the last three aspects supplying the mechanism that distinguishes
-a hyperlink from "`normal`" text and makes this a hypermedia control.
+So we have four aspects of a simple hypermedia link like this, with the last three aspects supplying the mechanism that
+distinguishes a hyperlink from "`normal`" text and, thus, makes this a hypermedia control.
Now, let's take a moment and think about how we can _generalize_ these last three aspects of a hyperlink.
@@ -99,10 +106,10 @@ Consider: what makes anchor tags (and forms) so special?
Why can't other elements issue HTTP requests as well?
For example, why shouldn't `button` elements be able to issue HTTP requests? It seems arbitrary to have to wrap a
-form tag around a button just to make deleting contacts work in our application.
+form tag around a button just to make deleting contacts work in our application, for example.
-Maybe: other elements should be able
-to issue HTTP requests as well, and act as hypermedia controls on their own.
+Maybe: other elements should be able to issue HTTP requests as well. Maybe other elements should be able to act as
+hypermedia controls on their own.
This is our first opportunity to generalize HTML as a hypermedia.
@@ -112,13 +119,13 @@ This is our first opportunity to generalize HTML as a hypermedia.
HTML could be extended to allow _any_ element to issue a request to the server and act as a hypermedia control.
====
-=== Why Only Clicks & Submits?
+=== Why Only Click & Submit Events?
Next, let's consider the event that triggers the request to the server on our link: a click event.
-Well, what's so special about clicking (in the case of anchors) or submitting (in the case of forms)? Those are just two
-of many, many events that are fired by the DOM, after all. Events like mouse down, or key up, or blur are all events
-you might want to use to issue an HTTP request.
+Well, what's so special about clicking (in the case of anchors) or submitting (in the case of forms) things? Those are
+just two of many, many events that are fired by the DOM, after all. Events like mouse down, or key up, or blur are all
+events you might want to use to issue an HTTP request.
Why shouldn't these other events be able to trigger requests as well?
@@ -164,10 +171,11 @@ HTML could be extended so that it allows access to the missing three HTTP method
As a final observation, consider the last aspect of a hyperlink: it replaces the _entire_ screen when a user clicks on it.
It turns out that this technical detail is the primary culprit for poor user experience in Web 1.0 Applications.
-A full page refresh can cause a flash of unstyled content, it destroys the scroll state of the user by scrolling to the
-top of the page, and so forth.
+A full page refresh can cause a flash of unstyled content, where content "jumps" on the screen as it transitions from
+its initial to its styled final form. It also destroys the scroll state of the user by scrolling to the
+top of the page, removes focus from a focused element and so forth.
-But there is no rule saying that hypermedia exchanges _must_ replace the entire document.
+But, if you think about it, there is no rule saying that hypermedia exchanges _must_ replace the entire document.
This gives us our fourth, final and perhaps most important opportunity to generalize HTML:
@@ -202,7 +210,7 @@ can be added to a web application by simply including it via a `script` tag in y
Because of this simple installation model, you can take advantage of tools like public CDNs to install the library.
-Below is an example using the popular https://unpkg.com[unpkg] Content Delivery Network (CDN) to install version `1.7.0`
+Below is an example using the popular https://unpkg.com[unpkg] Content Delivery Network (CDN) to install version `1.9.2`
of the library. We use an integrity hash to ensure that the delivered JavaScript content matches what we expect. This
SHA can be found on the htmx website.
@@ -213,9 +221,9 @@ We also mark the script as `crossorigin="anonymous"` so no credentials will be s
[source,html]
----
-
+
----
@@ -234,11 +242,10 @@ Once htmx has been installed, you can begin using it immediately.
=== No JavaScript Required...
-And here we get to the fun part of htmx: htmx does not require you,
-the user of htmx, to actually write any JavaScript.
+And here we get to the interesting part of htmx: htmx does not require you, the user of htmx, to actually write any JavaScript.
Instead, you will use _attributes_ placed directly on elements in your HTML to drive more dynamic behavior. Htmx extends
-HTML as a hypermedia, and it wants that extension to be as natural and consistent as possible with existing
+HTML as a hypermedia, and it is designed so that extension is as natural and consistent as possible with existing
HTML concepts. Just as an anchor tag uses an `href` attribute to specify the URL to retrieve, and forms use an `action`
attribute to specify the URL to submit the form to, htmx uses HTML _attributes_ to specify the URL that an HTTP request
should be issued to.
@@ -282,8 +289,8 @@ Very easy to understand and very consistent with the rest of HTML.
With the request issued by the button above, we get to perhaps the most important thing to understand about htmx:
it expects the response to this AJAX request _to be HTML_. Htmx is an extension of HTML. A native hypermedia control
-like an anchor tag will typically get an HTML response to a request it creates. Similarly, htmx expects the server to
-respond to the requests that it makes with HTML.
+like an anchor tag will typically get an HTML response to an HTTP request it creates. Similarly, htmx expects the server to
+respond to the requests that _it_ makes with HTML.
This may surprise web developers who are used to responding to an AJAX request with JSON,
which is far and away the most common response format for such requests. But AJAX requests are just HTTP requests and
@@ -341,10 +348,10 @@ content into the existing page (rather than replacing the entire page), the ques
content be placed?
It turns out that the default htmx behavior is to simply put the returned content inside the element that triggered the
-request. That's obviously _not_ a good thing in the case of our button: we will end up with a list of contacts awkwardly embedded within
+request. That's _not_ a good thing in the case of our button: we will end up with a list of contacts awkwardly embedded within
the button element. That will look pretty silly and is obviously not what we want.
-Fortunately htmx provides another attribute, `hx-target` which can be used to specify exactly where in the DOM the
+Fortunately htmx provides another attribute, `hx-target` which can be used to specify exactly _where_ in the DOM the
new content should be placed. The value of the `hx-target` attribute is a Cascading Style Sheet (CSS) _selector_ that
allows you to specify the element to put the new hypermedia content into.
@@ -465,15 +472,14 @@ four opportunities for improvement that we enumerated regarding plain HTML:
* Opportunity 1: We can now issue an HTTP request with _any_ element (in this case we are using a button).
* Opportunity 3: We can issue _any sort_ of HTTP request we want, `PUT`, `PATCH` and `DELETE`, in particular.
-And, with `hx-target` and `hx-swap` we have addressed a third shortcoming:
-the requirement that the entire page be replaced.
+And, with `hx-target` and `hx-swap` we have addressed a third shortcoming: the requirement that the entire page be replaced.
* Opportunity 4: We can now replace any element we want in our page via transclusion, and we can do so in any manner want.
So, with only seven relatively simple additional attributes, we have addressed most of the shortcomings of HTML as a
hypermedia that we identified earlier.
-What's next? Recall the other shortcoming we noted: the fact that only a `click` event (on an anchor) or a `submit` event
+What's next? Recall the one other opportunity we noted: the fact that only a `click` event (on an anchor) or a `submit` event
(on a form) can trigger a HTTP request. Let's look at how we can address that limitation.
== Using Events
@@ -547,7 +553,7 @@ Note that we have a comma separated list of events that can trigger this element
one potential triggering event. We still want to respond to the `click` event and load the contacts, in addition
to handling the `Ctrl-L` keyboard shortcut.
-There are, unfortunately, two problems with our `keyup` addition: As it stands, it will trigger requests on _any_ keyup
+Unfortunately there are two problems with our `keyup` addition: As it stands, it will trigger requests on _any_ keyup
event that occurs. And, worse, it will only trigger when a keyup occurs _within_ this button. The
user would need to tab onto the button to make it active and then begin typing.
@@ -625,7 +631,7 @@ outlined at the start of this chapter:
That's a grand total of eight, count 'em, _eight_ attributes that all fall squarely within the same conceptual model as
normal HTML and that, by extending HTML as a hypermedia, open up a whole new world of user interaction possibilities
-within HTML.
+within it.
Here is a table summarizing those opportunities and which htmx attributes address them:
@@ -876,59 +882,7 @@ conceptually coherent with the underlying markup language. Like any technical c
trade-offs: by staying so close to HTML, htmx does not give developers a lot of infrastructure that many might feel
should be there "`by default`".
-A good example is the concept of modal dialogs. Many web applications today make heavy use of modal dialogs, effectively
-in-page pop-ups that sit "`on top`" of the existing page. (Of course, in reality, this is an optical illusion and it is
-all just a web page: the web has no notion of "`modals`" in this regard.)
-
-A web developer might expect htmx, as a front end library, to provide some sort of modal dialog component out of the box.
-
-Htmx, however, has no such notion of modals. That's not to say you can't use modals with htmx, and we will look at how you
-can do so later. But htmx, like HTML itself, won't give you an API specifically for creating modals. You
-would need to use a 3rd party library or roll your own modal implementation and then integrate htmx into it if you want
-to use modals within an htmx-based application.
-
By staying closer to the original model of the web, htmx aims to strike a balance between simplicity and functionality,
deferring to other libraries for more elaborate frontend extensions on top of the existing web platform. The good news
is that htmx plays well with others, so when these needs arise it is often easy enough to bring in another library to handle
them.
-
-
-[.design-note]
-.HTML Note: Caution with Improvised UI Elements
-****
-Accessibility problems can arise when we try to implement controls that aren't built into HTML.
-
-For example, what if you make something that looks like a set of tabs, but you use radio buttons and CSS hacks to build it?
-
-The problem here is that tabs have requirements beyond clicking to change content.
-Your improvised tabs may be missing features that will lead to user confusion and frustration, as well as some undesirable behaviors.
-From the link:https://www.w3.org/WAI/ARIA/apg/patterns/tabs/[ARIA Authoring Practices Guide on tabs]:
-
-* Keyboard interaction
-
-** Can the tabs be focused with the Tab key?
-
-* ARIA roles, states, and properties
-
-** "`[The element that contains the tabs] has role `tablist`.`"
-
-** "`Each [tab] has role `tab` [...]`"
-
-** "`Each element that contains the content panel for a `tab` has role `tabpanel`.`"
-
-** "`Each [tab] has the property `aria-controls` referring to its associated tabpanel element.`"
-
-** "`The active `tab` element has the state `aria-selected` set to `true` and all other `tab` elements have it set to `false`.`"
-
-** "`Each element with role `tabpanel` has the property `aria-labelledby` referring to its associated `tab` element.`"
-
-You would need to write a lot of code to make your improvised tabs fulfill all of these requirements. Some of the ARIA attributes can be added directly in HTML,
-but they are repetitive
-and others (like `aria-selected`) need to be set through JavaScript since they are dynamic.
-The keyboard interactions can be error-prone too.
-
-It's not impossible to make your own tab set implementation.
-However, it's difficult to trust that a new implementation will work in all environments, since most of us have limited access to testing devices.
-
-Stick with established libraries for UI interactions. If a use case requires an improvised solution, test carefully for keyboard interaction and accessibility.
-****
\ No newline at end of file
diff --git a/book/CH05_htmxPatterns.adoc b/book/CH05_htmxPatterns.adoc
index cbf329c..f902946 100644
--- a/book/CH05_htmxPatterns.adoc
+++ b/book/CH05_htmxPatterns.adoc
@@ -1,7 +1,7 @@
= Htmx Patterns
:chapter: 05
-:url: ./htmx-in-action/
+:url: /htmx-in-action/
Now that we've seen how htmx extends HTML as a hypermedia, it's time to put it into action. As we use htmx, we will still
be using hypermedia: we will issue HTTP requests and get back HTML. But, with the additional functionality that htmx provides,
@@ -255,10 +255,14 @@ support and so on. And, if JavaScript isn't enabled, it will fall back to the n
All this with one htmx attribute.
-The `hx-boost` attribute is more "`magic`" than others. Htmx attributes generally are lower level and require more explicit
-annotation in order to specify exactly what you want htmx to do. In general, this is the design philosophy of htmx:
-prefer explicit to implicit and obvious to "`magic.`" However, the `hx-boost` attribute is too useful to allow dogma to
-override practicality, and so it is included as a feature in the library.
+The `hx-boost` attribute is neat, but is different than other htmx attributes in that it is pretty "`magical`": by
+making one small change you modify the behavior of a large number of elements on the page, turning them into
+AJAX-powered elements. Most other htmx attributes are generally lower level and require more explicit annotations in
+order to specify exactly what you want htmx to do. In general, this is the design philosophy of htmx: prefer explicit
+over implicit and obvious over "`magic.`"
+
+However, the `hx-boost` attribute was too useful to allow dogma to override practicality, and so it is included as a
+feature in the library.
== A Second Step: Deleting Contacts With HTTP DELETE
@@ -308,9 +312,9 @@ A couple of things to notice:
Note that we have done something pretty magical here: we have turned this button into a _hypermedia control_. It is no
longer necessary that this button be placed within a larger `form` tag in order to trigger an HTTP request: it is a
stand-alone, and fully featured hypermedia control on its own. This is at the heart of htmx, allowing any element to become
-a hypermedia control and fully participate in the Hypermedia-Driven Application.
+a hypermedia control and fully participate in a Hypermedia-Driven Application.
-We should note that, unlike with the `hx-boost` examples above, this solution will _not_ degrade gracefully. To make
+We should also note that, unlike with the `hx-boost` examples above, this solution will _not_ degrade gracefully. To make
this solution degrade gracefully, we would need to wrap the button in a form element and handle a `POST` on the server
side as well.
@@ -489,9 +493,9 @@ all while using declarative attributes in our HTML and staying firmly within the
=== Progressive Enhancement?
-One thing to note about this solution, however, is that it is _not_ a progressive enhancement to our web application: if
-someone has disabled JavaScript then this "`Delete Contact`" button will no longer work. We could do additional work to keep
-the older mechanism working in a JavaScript-disabled environment.
+As we noted earlier about this solution: it is _not_ a progressive enhancement to our web application: if
+someone has disabled JavaScript then this "`Delete Contact`" button will no longer work. We would need to do additional
+work to keep the older form-based mechanism working in a JavaScript-disabled environment.
Progressive Enhancement can be a hot-button topic in web development, with lots of passionate opinions and perspectives.
Like nearly all JavaScript libraries, htmx makes it possible to create applications that do not function in the absence of
@@ -826,7 +830,7 @@ experience to our web application. Even better, any email validation rules we a
_automatically_ just work using this model: because we are using hypermedia as our communication mechanism there is no
need to keep a client-side and server-side model in sync with one another.
-A great demonstration of the power of the hypermedia architecture.
+A great demonstration of the power of the hypermedia architecture!
== Another Application Improvement: Paging
@@ -838,7 +842,7 @@ all 10,000 contacts on the root page. Showing so much data can bog a browser (a
adopt a concept of "`paging`" to deal with data sets this large, where only one "`page`" of a smaller number of items is
shown, with the ability to navigate around the pages in the data set.
-Let's fix our application, so that we only show ten contacts at a time with a "`Next`" and "`Previous`" link if there are more
+Let's fix our application so that we only show ten contacts at a time with a "`Next`" and "`Previous`" link if there are more
than 10 contacts in the contact database.
The first change we will make is to add a simple paging widget to our `index.html` template.
@@ -904,7 +908,7 @@ knows which page to return.
And, with that small change, we are done: we now have a very basic paging mechanism for our web application.
-And, believe it or not, it is already using AJAX, thanks to our use of `hx-boost` in the application. Easy.
+And, believe it or not, it is already using AJAX, thanks to our use of `hx-boost` in the application. Easy!
=== Click To Load
@@ -1033,9 +1037,9 @@ behavior, we are still exchanging hypermedia with the server, with no JSON API r
As the web was designed.
-
+// TODO dz4k rewrite
[.design-note]
-.Component Soup?
+.HTML Notes: Framework Soup
****
Components encapsulate a section of a page along with its dynamic behavior.
While encapsulating behavior is a good way to organize code,
@@ -1049,17 +1053,14 @@ Before you reach for components for reuse, consider your options.
Lower-level mechanisms often (allow you to) produce better HTML.
In some cases, components can actually _improve_ the clarity of your HTML.
-To decide if a component is appropriate for your use case, a good rule of thumb is to ask:
-"`Could this reasonably be a built-in HTML element?`"
-For example, a code editor is a good candidate,
-since HTML already has `