Huh?  What?  Why?

This article walks through the history of the internet, and the rise of the World Wide Web, leading up to the design and development of the Hashtag Framework.

Hello, Internet

The early internet brought along with it the capability to globally distribute well-formatted information.   The basic needs were text alignment, simple font styling, and the ability to link to other sources of information.   A browser program would be used to request this information and format it accordingly.  

Most systems at the time (early 1990s) supported at least one rich-text editor used to create printable documents, or share well-formatted information with other users of the same program.   Each of those rich-text editors had their own file formats that were notoriously incompatible with each other.   As editor programs added new features, files produced by them were often incompatible with previous versions of the same program.   Similar issues were destined to surface as browsers added features, and can still be seen today when websites look different in different browsers.  

Avoiding those incompatibility issues on the editor side would be key to obtaining adoption by content creators, so only a raw text editor would be required.   With this understanding, a method was needed for representing well-formatted information using only a raw text editor.  

Hello, HyperText

The HyperText Markup Language (HTML) offered <tags> to represent well-formatted information.   The HyperText Transfer Protocol (HTTP) defined how browsers should request content, and how servers should respond to those requests.   HTTP took advantage of the relatively new Domain Name System (DNS), which provided a simple way to address servers on the internet.   Browsers would input a Uniform Resource Locator (URL), apply DNS, then send a request to the server.   HTTP servers would accept those requests, map them to files on the server, then return the file content.  

The web of linked HTML content grew quickly, as content creation was as simple as using a raw text editor, and understanding how markup like "<b>bold</b>" results in "bold".   To learn more, see A history of HTML by The World Wide Web Consortium (W3C), or the original HyperText proposal by Tim Berners-Lee to CERN management, or the Wikipedia articles for HTML and Web Browsers, or HTTP and Web Servers.  

Browser Standardization

As HTML adoption took hold, new browsers competed by offering custom features, such as Cookies for storing information in the browser that would be included with all subsequent requests to the same domain.   Cookies provided the capability of stateful end-user sessions, giving rise to the shopping cart.   The subsequent browser wars evolved the recognition of standards shared by all major browsers.  

The Document Object Model (DOM) defined how browsers should represent the parsed state of HTML, Cascading Style Sheets (CSS) allowed entire classes of DOM objects to be styled uniformly, and JavaScript provided a programming language for processing and automation within browsers.   To learn more, see the Wikipedia articles for JavaScript, the Document Object Model (DOM), or Cascading Style Sheets (CSS).

Content creators strived for these standards, as creating multiple versions of the same content was not feasible.   JavaScript and CSS libraries, such as jQuery and Bootstrap, evolved to provide means to create a single source of content with predictable and uniform results for all browsers on all devices.  

Server-Side Processing

For websites to offer guestbooks, hit counters, and checkout processes for shopping carts, a method was needed for processing the submitted data server-side.   The Common Gateway Interface (CGI) provided a framework for routing HTTP requests to executable programs on the server.   Perl was a popular programming language for CGI, as it was designed for text processing, and didn't require a compiler or any build tools other than a raw text editor.   HTTP servers configured to use CGI would map URL paths beginning with "/cgi-bin/" to CGI scripts that would be executed.   To learn more, see the Wikipedia article for the Common Gateway Interface.  

Although CGI provided a viable method for server-side processing, it didn't scale well, as it spawned a new process to execute CGI scripts on top of the HTTP server process.   Many CGI scripts would store data in files on the server, creating many security and reliability issues.   Database programs solved many of these issues, providing a Structured Query Language (SQL) for storing data and generating reports.   CGI was notoriously prone to text injection exploits (file paths, SQL, HTML), often resulting in an attacker obtaining total access to the system.  

Hello, PHP

PHP overcame the drawbacks of CGI by integrating directly with HTTP servers, and offering a programming language especially suited to web development.   PHP could automatically manage end-user session cookie HTTP headers, and interface with most SQL databases.   Using a few shared configuration files and templates, PHP makes it relatively easy to create dynamic Web Apps.   To learn more about PHP, visit php.net.

Consider the following pieces that make up a simple guestbook signature process, using PHP with a SQL database.

  • HTML form sent to the browser:
    <form method="post" action="/sign-guestbook.php">
    	Name:<br>
    	<input type="text" name="name" size="50"><br>
    	Comment:<br>
    	<textarea name="comment" rows="4" cols="50"></textarea><br>
    	<input type="submit" value="Sign Guestbook!">
    </form>
  • SQL schema defining how the server-side database will store records:
    CREATE TABLE `guestbook` (
    	`id` int NOT NULL auto_increment,
    	`created_on` timestamp NOT NULL default CURRENT_TIMESTAMP,
    	`name` text NOT NULL default '',
    	`comment` text NOT NULL default '',
    	PRIMARY KEY (`id`)
    );
  • PHP form handler to process the submitted data server-side:
    <?php
    // ... $db initialized as a PHP Database Object
    $sql = "INSERT INTO `guestbook` 
    		SET `name`=:name,
    			`comment`=:comment;";
    $params = array(
    	':name'=>$_POST['name'], 
    	':comment'=>$_POST['comment']
    );
    $query = $db->prepare($sql);
    $query->execute($params);

Now consider adding an email address field to this guestbook process, and how it would require changes to each of those 3 pieces.  

  • HTML form changes:
    <form method="post" action="/sign-guestbook.php">
    	Name:<br>
    	<input type="text" name="name" size="50"><br>
    	Email Address:<br>
    	<input type="email" name="email" size="50"><br>
    	Comment:<br>
    	<textarea name="comment" rows="4" cols="50"></textarea><br>
    	<input type="submit" value="Sign Guestbook!">
    </form>
  • SQL schema changes:
    ALTER TABLE `guestbook`
    	ADD COLUMN `email` text NOT NULL default '';
  • PHP form handler changes:
    <?php
    // ... $db initialized as a PHP Database Object
    $sql = "INSERT INTO `guestbook` 
    		SET `name`=:name,
    			`email`=:email,
    			`comment`=:comment;";
    $params = array(
    	':name'=>$_POST['name'],
    	':email'=>$_POST['email'],
    	':comment'=>$_POST['comment']
    );
    $query = $db->prepare($sql);
    $query->execute($params);

These multiple changes, in multiple places, caused many development issues, especially when deploying changes between testing and production environments.   PHP Object Oriented Programming offered solutions to consolidate all of the pieces into a single PHP file, however, multiple changes in a single file still didn't solve the fundamental issues with multiple steps for every change.  

Although the guestbook examples above are functional, they are lacking in many ways.   To support smaller handheld screens, the HTML form should use CSS classes that respond to screen size.   To assist screen-readers and adaptive technologies, the HTML form should link labels to their corresponding inputs using ARIA attributes.   The PHP form handler should validate the submitted email address, and limit the length of the guestbook comments.   The guestbook form should also use a CAPTCHA system to prevent spambots, and a profanity filter or moderation system to curb abuse.   Faced with these mounting requirements, many content creators turn to prebuilt solutions.  

Frameworks Galore

Model-View-Controller (MVC) frameworks provided standardization for development practices.   The MVC web development process is generally the same as the PHP examples above;  the SQL data schema is a Model, the HTML form is a View, and the PHP form handler is a Controller.   Example MVC frameworks for PHP include Laravel, CodeIgniter, CakePHP, Symfony, Zend, and dozens more.   These frameworks generally mean learning a completely new way to define the same old web processes.   For all that MVC frameworks do to stop you from shooting yourself in the foot while reinventing the wheel, they generally don't change the web development process much beyond that.

Content Management Systems (CMS) brought the web development process directly into the website itself.   Web based tools made adding a field to an existing form as simple as clicking a button, and setting a few attributes, all in 1 step.   Example CMS frameworks for PHP include WordPress, Joomla, Drupal, and dozens more.   CMS Plugin and Theme marketplaces offered prebuilt solutions for almost everything.   For all of the issues solved by a CMS, they blur the line between application and data, abandoning the raw text editor for web based tools prone to injection exploits and incompatibility issues between versions and 3rd party extensions.  

Outside of PHP, many other languages provided web frameworks that used raw text source files.   Examples include Ruby on Rails, Django for Python, Spring for Java, and dozens more.   All of these frameworks provide viable web solutions, but they come with steep learning curves.   Rewriting a website for one of these frameworks, that was originally built for a different framework, is not a simple task.  

Back to Web Standards

Many content creators were hesitant to bring another language into the mix of HTML, JavaScript, and CSS; so most modern web frameworks have adopted JavaScript for everything.   This includes server-side processing and DOM rendering.   Example JavaScript frameworks include Node.js, AngularJS, ReactJS, Vue.js, and dozens more.  

Vue.js published a comparison of JavaScript frameworks, presenting sample solutions, by framework, for the simple task of processing a list of items.   The requirements include placing the results in an HTML <div> tag, applying the CSS attribute class="list-container".   If the list of items is empty, an HTML <p> tag will be created containing a "No items found." message;  otherwise an HTML <ul> tag will be created with an <li> tag for each item containing its name;  

ReactJS

  • In ReactJS, everything is a component, which is essentially a JavaScript function.   This example assumes the component has already fetched the list of items in another process, and stored the data in the props attribute of this component.  

    render () {
      let { items } = this.props
      let children
      if (items.length > 0) {
        children = (
          <ul>
            {items.map(item =>
              <li key={item.id}>{item.name}</li>
            )}
          </ul>
        )
      } else {
        children = <p>No items found.</p>
      }
      return (
        <div className='list-container'>
          {children}
        </div>
      )
    }

The <ul> tags that look like HTML are actually JSX, which brings XML syntax to JavaScript.   One of the differences between React JSX and HTML can be seen in final <div> container, React JSX uses className instead of class to avoid JavaScript reserved word conflicts.   Values are injected using {item.name} syntax, but it isn't clear how that value is made safe for HTML injection.   Consider a malicious user providing an item.name value of "pwnd</li></ul>", injecting it as provided would instruct browsers to prematurely end the list.   {item.name} was injected into children, and then {children} was later injected into the container <div>, so it seems the {item.name} value must have already been made safe for HTML injection.  

Vue.js

  • Extending MVC methodologies, Vue.js creates views in a .vue file that uses <template> tags to define the HTML, <script> tags to define any JavaScript needed to process or acquire data, and <style> tags to define CSS properties for the template, usually using a CSS pre-processor like Stylus.   This example focuses only on the <template> tag.  

    <template>
      <div class="list-container">
        <ul v-if="items.length">
          <li v-for="item in items">
            {{ item.name }}
          </li>
        </ul>
        <p v-else>No items found.</p>
      </div>
    </template>

Vue.js templates improve upon JSX by supporting any valid HTML content.   The HTML tag attributes v-if and v-else are Vue.js controls for limiting which tags are rendered.   The logic of those controls is inside-out compared to most other programming languages, as the start of the tag that may be rendered comes before the start of the v-if attribute that implies it might not be rendered.   The v-for attribute creates a loop structure that renders the enclosing tag for every item in the list.   The {{ item.name }} syntax injects the name value, and encodes it to avoid HTML injection.   To override this automatic HTML encoding, Vue.js offers the v-html="rawHtml" control, but you cannot use that injected HTML content to compose the template further.   Although the Vue.js template controls solve many basic needs, anything more complex requires falling back to a JSX syntax similar to the ReactJS example above.  

The State of Web Development

Too many frameworks to count.   Many web frameworks have adopted JavaScript as a primary language on both the front‑end and back‑end.   Using JavaScript on the back‑end allows for code re-use between the front‑end and back‑end, but each framework has its own methods for processing and storing back‑end data.   Using back‑end JavaScript also eliminates the need to learn a different programming language, but it still requires learning the framework-specific methods for programming back‑end JavaScript.  

Most modern web frameworks heavily utilize CSS, but content creators are often frustrated when small padding or alignment tweaks require multiple changes in multiple places.   CSS pre-processors emerged to extend CSS through a compiling process that generates the final CSS files.   The features provided by CSS pre-processors include functions, variables, mix-ins, interpolations, and more.   Example CSS pre-processors include LESS, Sass, Stylus, and dozens more.   CSS frameworks emerged to bundle CSS with the JavaScript needed to maintain the CSS consistently on all devices and browsers.   Many CSS frameworks support responsive grid layouts that reorganize content based on browser screen size, eliminating the need to develop separate content for mobile devices.   Example CSS frameworks include Bootstrap, Foundation, Skeleton, and dozens more.  

Many new programming languages have emerged that provide compile targets for many JavaScript versions and frameworks.   These new languages take advantage of the robust support of JavaScript web frameworks, while also providing powerful development tools and libraries.   Some of these languages provide their own CSS pre-processor features, while others integrate with existing CSS pre-processors.   Example languages that compile to JavaScript include CoffeeScript, TypeScript, Babel, and dozens more.  

Taking A Look Around

Many content creators have embraced version control systems, especially if they are working in teams or corporate environments.   The systems can track every change of content, including who made it and when, with the ability to roll-back any change to any previous version.   Multiple changes can be made to the same file by different people, with all changes merged into a new version.   Example version control systems include Git, Mercurial, Subversion, and dozens more.  

As version control systems became a fixture in many development environments, the version control processes took on additional roles.   Quality Assurance tasks were easily hooked in, such as running automated tests after every build, or triggering a compiler or pre-processor to run whenever new content is submitted.   Operational tasks were also hooked in, such as setting up and deploying servers to host the latest content.   In many cases, no additional development steps are needed for running compilers or pre-processors, as the version control processes absorb the costs.  

Development processes have often become so complex that DevOps engineering roles are now common, often tasked with reusing the same content to build for multiple target platforms.   Google Accelerated Mobile Pages (AMP), now offer optimization techniques for content creators desiring a higher rank, requiring a special version of content to be built and submitted to their central authority.   Trusting a central authority to approve and serve cached content goes against the original tenets of web decentralization, however, these services can provide enhanced consumer experiences.   Requiring additional development steps for compilers and build processes is far cry from the sole raw text editor that empowered the original web.  

Hello, Hashtag

The Hashtag Markup Language extends HTML using <# tags #>.   The development process is the same as it was for the original web, requiring only a raw text editor.   The Hashtag Framework serves as a processing core for the Hashtag Markup Language, and much like PHP, it is especially suited for web development.  

Revisiting the PHP guestbook examples from above, a single block of Hashtag Markup can replace and consolidate all of those pieces, including the HTML form, the SQL database schema, and the back‑end form handler:

<# start form for guestbook; #>
	Name:<br>
	<input type="text" <# name #> size="50"><br>
	Comment:<br>
	<textarea <# comment #> rows="4" cols="50"></textarea><br>
	<input type="submit" <# create button #> value="Sign Guestbook!">
<# end form #>

When this Hashtag Form is processed, the Hashtag Framework ensures the SQL table guestbook exists, including columns for the referenced fields name and comment, and additional default columns, such as ID, and timestamps for Created On and Updated On.   A secure back‑end form handler is ready, that will only accept responses from this specific instance of the Hashtag Form.   The process for adding a new email field to the form, as in the PHP examples above, is done with a single markup change:  

<# start form for guestbook; #>
	Name:<br>
	<input type="text" <# name #> size="50"><br>
	Email Address:<br>
	<input type="email" <# email #> size="50"><br>
	Comment:<br>
	<textarea <# comment #> rows="4" cols="50"></textarea><br>
	<input type="submit" <# create button #> value="Sign Guestbook!">
<# end form #>

Save the changes, and you're done.   The Hashtag Form above uses HTML markup that has been universally supported since the earliest web browsers, however, it lacks the features listed under the PHP examples above, including the need to support modern assistive technologies, such as screen readers for the blind.   By embracing modern JavaScript and CSS frameworks, a few simple markup changes can provide all those missing features.   The following Hashtag Form extends the previous example by adopting jQuery and Bootstrap:

<# start form for guestbook; 
	set form.class to "form-horizontal";
	when creating redirect to "/guestbook";
#>
	<div class="form-group">
		<label class="control-label" for="name">Name</label>
		<input type="text" <# name #> class="form-control" id="name">
	</div>
	<div class="form-group">
		<label class="control-label" for="email">Email Address</label>
		<input type="text" <# email #> class="form-control" id="email">
	</div>
	<div class="form-group">
		<label class="control-label" for="note">Comment</label>
		<textarea <# comment #> class="form-control" id="note"></textarea>
	</div>	
	<button <# create button #> class="btn btn-primary" type="submit">
		Sign Guestbook!
	</button>
<# end form #>

The additional markup ensures the Hashtag Form will render consistently on all web browsers, and automatically adapt to smaller touch-screens and mobile devices.   A Form Action was added to automatically redirect to /guestbook after records are created.  

Revisiting the ReactJS and Vue.js examples from above, the following Hashtag List solves the same requirements.   The major difference from those examples, is the single block of Hashtag Markup consolidates everything else needed to fetch and render the data.   The following Hashtag List uses the data from the SQL table guestbook created in the previous example:

<div class="list-container">
<# start list for guestbook; #>
	<# start header #>
	<ul>
	<# end header #>
	<# start row #>
		<li><# name as html #></li>
	<# end row #>
	<# start footer #>
	</ul>
	<# end footer #>
	<# start no results #>
	<p>No items found.</p>
	<# end no results #>
<# end list #>
</div>

This Hashtag List includes the name field from every guestbook entry.   The List Templates are defined between <# start … #> and <# end … #> tags.   If any records exist, the header template is processed first, then the row template is processed for each record, and finally the footer template is processed.   If no records exists, only the no results template is processed.   The templates provide a quick transition to or from any other web framework, as any raw HTML or JavaScript can be copied and pasted in and out of any template.   This works because the logic controlling what to include is kept separate from the content being included.   Hashtag Lists support pagination, filtering, totaling calculations, and much more.  

The name value from each guestbook entry was added using the <# name as html #> tag.   A Hashtag Context was set in that tag, as html, which will encode HTML special characters in the name value so they are not interpreted as HTML by a web browser.   This eliminates the risk of HTML or JavaScript injection exploits, and all the transcoding issues you see when &amp; is shown instead of &, or &#39; instead of ', or &quot; instead of ".   The Hashtag Framework offers far more features than what these simple examples demonstrate.   By further embracing modern JavaScript and CSS frameworks, the Hashtag Framework provides simple solutions for almost any application.  

Ready To Go?

To learn more, check out the Hashtag Framework Overview

To see the Hashtag Framework in action, try the Build Acceptance Test