4elements, Amsterdam, Holland

  1. BDD With Behat

    The BDD PHP framework Behat, allows you to test your PHP applications using human-readable sentences to write features and scenarios about how your applications should behave in order to test out its functionality. We can then run these tests to see if our application is behaving as expected. Let’s spend about 15 minutes quickly going over Behat’s installation process and learn how we can test our PHP applications behavior using the basics.


    Installation

    To begin testing with Behat, we just need to install it on our local development machine. I’ll be using Composer, but you can take a look at a the documentation for additional installation methods.

    Within your PHP application (I have a blank PHP app named phpbehat created in advance) create a composer.json file with the following code to load in Behat:

    {
    	"require": {
    		"behat/behat": "2.4.*@stable"
    	},
    	"minimum-stability": "dev",
    	"config": {
    		"bin-dir": "bin/"
    	}
    }
    

    In your terminal we can install it using the following command:

    composer update

    We should now be able to run the bin/behat command to work with Behat.


    Creating Features

    We always begin by creating a new feature. A feature is something that we can use to describe a feature of our application and then implement it to get the test to pass.

    A feature, at its simplest, consists of:

    • Human-readable, plain text.
    • Uses a .feature extension.
    • Contains the feature’s benefit, role, and the feature itself.
    • May hold a list of scenarios.

    Now I can’t show you how to test all possible features for an application, as that would take far too long. But what I can do is show you how to go about writing a basic feature and you can adapt this code to make it work for your specific application.

    Testing the Phpadder Class

    To avoid complicating the learning process, let’s create a very simple Phpadder.php file which contains a couple methods that we can use to add two numbers together and display their sum.

    class Phpadder {
    
    	private $a;
    	private $b;
    	public $sum;
    
    	public function __construct($a, $b) {
    		$this->a = $a;
    		$this->b = $b;
    	}
    
    	public function add() {
    		$this->sum = $this->a + $this->b;
    	}
    
    	public function display() {
    		return $this->sum;
    	}
    }
    

    This creates a new class named Phpadder. We have a few properties to hold the first ($a) and second ($b) numbers to be added, as well as a $sum property to hold the values’s sum.

    Next, we have our constructor which initializes our properties. Then we have an add method to add the two numbers together and finally a display method to display the sum of the two numbers.

    Adder Feature

    Let’s now test this Phpadder class. Create a new .feature file along with the following code:

    # features/phpadder.feature
    Feature: adder
    	In order to display the sum of two numbers
    	As anybody
    	I need to provide two numbers
    

    We start out by giving our feature a name of adder. Then we specify, on three lines, the feature’s benefit, role, and finally the feature itself. It should be fairly self explanatory.

    Now that we have our feature, let’s start writing our scenarios.


    Creating Scenarios

    Anytime we create a feature we can define scenarios that describe how that feature behaves given certain conditions. Scenario’s follow the same basic layout consisting of the scenario’s description, a context, an event, and an outcome.

    Let’s create a scenario to test out our Phpadder application:

    Scenario: Display the sum of two provided numbers
    	Given I have the number 50 and the number 25
    	When I add them together
    	Then I should get 75
    

    We begin with our scenario description, we then list out that we start with the two numbers of 50 and 25 and when they are added together it should display the sum of 75.

    You can also have multiple contexts, events, and outcomes as well using the following keywords: And and But. Here’s a modified example of the previous scenario where we’ll use And:

    Scenario: Display the sum of two provided numbers
    	Given I have the number 50 and the number 25
    	And I have a third number of 25
    	When I add them together
    	Then I should get 100
    

    Creating Step Definitions

    A step is nothing more than a PHP function which is made up of a keyword, a regular expression, and a callback function. Each statement within your scenario will be matched to a step. These steps define what should happen given one of your statements are called within a scenario. You store all of your steps within the features/bootstrap/FeatureContext.php file.

    The “Given” Step

    In our FeatureContext.php file (you may need to create this), we need to write a step for each of our statements, using its name as the function name. We’ll start with the "Given I have the number" statement:

    # features/bootstrap/FeaturesContext.php
    
    require("Phpadder.php");
    
    use Behat\Behat\Context\BehatContext, 
    	Behat\Behat\Exception\PendingException;
    
    use Behat\Gherkin\Node\PyStringNode,
    	Behat\Gherkin\Node\TableNode;
    	
    class FeatureContext extends BehatContext {
    
    	private $Adder;
    	
    	/**
    	 * @Given /^I have the number (\d+) and the number (\d+)$/
    	 */
    	public function iHaveTheNumberAndTheNumber($a, $b) {
    		$this->Adder = new Phpadder($a, $b);
    	}
    

    First, we create a new PHP file, require in our Phpadder.php file (the file that we’re testing), and then we use a few Behat classes with use statements, right after.

    Next, we create our FeatureContext class and have it extend the BehatContext class.

    Our class has only one property, $Adder, which will hold a Phpadder object.

    Finally, we create a method for our first step using the same name as the statement. Our step has a regular expression, found within the method’s comment. This regular expression is used to match the step to a scenario statement. Within this method we simply assign a new Phpadder object to our $this->Adder property so that the rest of our methods have access to the same Phpadder object.

    Now, you’ve probably noticed the @Given keyword within your function’s comment, this is actually an annotation so that the different types of steps can be identified. You can use @Given, @When, and @Then.

    Now we just need to write the last two steps.

    The “When” Step

    /**
     * @When /^I add them together$/
     */
    public function iAddThemTogether() {
    	$this->Adder->add();
    }
    

    This step simply uses our $this->Adder object’s add method to add the two numbers together.

    The “Then” Step

    /** 
     * @Then /^I should get (\d+)$/ 
     */
    public function iShouldGet($sum) {
    	if ($this->Adder->sum != $sum) {
    		throw new Exception("Actual sum: ".$this->Adder->sum);
    	}
    	$this->Adder->display();
    }
    

    This step starts off by checking if the actual sum (retrieved using our $this->Adder object and its sum property) is not equal to the expected sum. If this evaluates to true that means we need to have Behat show a failure. To do so, we’ll just throw a new exception displaying the actual sum so we can compare. Otherwise, we call our display method.

    Time to run the tests.


    Running the Tests

    Now that we have our features, scenarios, and steps laid out, let’s run our tests using the following command:

    bin/behat
    

    You should see the following success messages inside of your terminal:

    testing-success

    You can ensure that your tests are running correctly, by simply breaking something in your Phpadder.php file so that it doesn’t run quite the same way your test expects it to. For example, if we change the add method to instead use subtraction, like so:

    public function add() {
    	$this->sum = $this->a - $this->b;
    }
    

    And then we rerun our tests: bin/behat. You can see in our terminal, we now have a failing test, because it’s no longer adding our numbers but subtracting them:

    testing-fail

    Conclusion

    In conclusion, you can follow a small four step process for testing your PHP apps using Behat:

    1. Define a Feature
    2. Define a Scenario
    3. Define Step Definitions
    4. Run the tests using bin/behat

    So, with just that small amount of code, we should now have a basic understanding of how to work with Behat to test our PHP applications. For more information about working with Behat please checkout their documentation.

     

    0 Comments

    Leave a comment › Posted in: Daily

    1. Intro to Shadow DOM

      Take any modern web page and you will notice that it invariably contains content stitched together from a variety of different sources; it may include the social sharing widgets from Twitter or Facebook or a Youtube video playing widget, it may serve a personalized advertisement from some ad-server or it may include some utility scripts or styles from a third party library hosted over CDN and so on. And if everything is HTML based (as is preferred these days) there is a high probability of collisions between the markup, scripts or styles served from various sources. Generally, namespaces are employed to prevent these collisions which solve the problem to some extent, but they don’t offer Encapsulation.

      Encapsulation is one of the pillars on which the Object Oriented Programming paradigm was founded and is normally used to restrict the internal representation of an object from the outside world.

      Coming back to our problem, we can surely encapsulate the JavaScript code using closures or using the module pattern but can we do the same for our HTML markup? Imagine that we have to build a UI widget, can we hide the implementation details of our widget from the JavaScript and CSS code that is included on the page, which consumes our widget? Alternatively, can we prevent the consuming code from messing up our widget’s functionality or look and feel?


      Shadow DOM to the Rescue

      The only existing solution that creates a boundary between the code you write and code that consumes, is ugly – and operates by using a bulky and restrictive iFrame, which brings with itself another set of problems. So are we forced to adapt to this approach always?

      Not anymore! Shadow DOM provides us an elegant way to overlay the normal DOM subtree with a special document fragment that contains another subtree of nodes, which are impregnable to scripts and styles. The interesting part is that it’s not something new! Various browsers have already been using this methodology to implement native widgets like date, sliders, audio, video players, etc.

      Enabling Shadow DOM

      At the time of this writing, the current version of Chrome (v29) supports inspecting Shadow DOM using Chrome DevTools. Open Devtools and click on the cog button at the bottom right of the screen to open the Settings panel, scroll down a bit and you will see a checkbox for showing Shadow DOM.

      Turn on Shadow DOM

      Now that we have enabled our browser, lets check out the internals of the default audio player. Just type:

      <audio width="300" height="32" src="http://developer.mozilla.org/@api/deki/files/2926/=AudioTest_(1).ogg" autoplay="autoplay" controls="controls">
       Your browser does not support the HTML5 Audio.
       </audio>
      

      Into your HTML markup. It shows the following native audio player in supported browsers:

      audio_player

      Now go ahead and inspect the audio player widget that you just created.

      Shadow DOM of Native Date Widget

      Wow! It shows the internal representation of the audio player, which was otherwise hidden. As we can see, the audio element uses a document fragment to hold the internal contents of the widget and appends that to the container element ( which is known as Shadow Host ).

      Shadow Host & Shadow Root

      • Shadow Host: is the DOM element which is hosting the Shadow DOM subtree or it is the DOM node which contains the Shadow Root.
      • Shadow Root: is the root of the DOM subtree containing the shadow DOM nodes. It is a special node, which creates the boundary between the normal DOM nodes and the Shadow DOM nodes. It is this boundary, which encapsulates the Shadow DOM nodes from any JavaScript or CSS code on the consuming page.
      • Shadow DOM: allows for multiple DOM subtrees to be composed into one larger tree. Following images from the W3C working draft best explains the concept of overlaying the nodes. This is how it looks before the Shadow Root’s content are attached to Shadow Host element:
        Normal Document Tree & Shadow DOM Subtrees

        When rendered, the Shadow tree takes place of Shadow Host’s content.

        Composition Complete

        This process of overlaying the nodes is often referred to as Composition.

      • Shadow Boundary: is denoted by the dotted line in the image above. This denotes the separation between the normal DOM world and the Shadow DOM world. The scripts from either side cannot cross this boundary and create havoc on the other side.

      Hello Shadow DOM World

      Enough chit-chat I say, Let’s get our hands dirty by writing some code. Suppose we have the following markup, which shows a simple welcome message.

      <div id="welcomeMessage">Welcome to My World</div>
      

      Add the following JavaScript code or use this Fiddle:

      
      var shadowHost = document.querySelector("#welcomeMessage");
      var shadowRoot = shadowHost.webkitCreateShadowRoot();
      shadowRoot.textContent = "Hello Shadow DOM World";
      
      

      Here we create a Shadow Root using the webkitCreateShadowRoot() function, attach it to a Shadow Host and then simply change the content.

      Notice the vendor-specific prefix webkit before the function name. This indicates that this functionality is currently supported on some webkit-based browsers only.

      If you go ahead and run this example in a supported browser, then you would see “Hello Shadow DOM World” instead of “Welcome to My World” as the Shadow DOM nodes have over-shadowed the normal ones.

      Disclaimer: As some of you may notice, we’re mixing the markup with scripts, which is generally not recommended and Shadow DOM is no exception. We have deliberately avoided the use of templates so early in the game in order to avoid any confusion. Otherwise Shadow DOM does provide an elegant solution to this problem and we will get there pretty soon.


      Respecting Shadow Boundary

      If you try and access the content of the rendered tree using JavaScript, like so:

      var shadowHost = document.querySelector("#welcomeMessage");
      var shadowRoot = shadowHost.webkitCreateShadowRoot();
      shadowRoot.textContent = "Hello Shadow DOM World";
      
      console.log(shadowHost.textContent);
       // Prints "Welcome to My World" as the shadow DOM nodes are encapsulated and cannot be accessed by JavaScript
      

      You will get the original content “Welcome to My World” and not the content which is actually rendered on the page, as the Shadow DOM tree is encapsulated from any scripts. This also means that the widget that you create using Shadow DOM is safe from any unwanted/conflicting scripts already present in the page.

      Styles Encapsulation

      Similarly, any CSS selector is forbidden to cross the shadow boundary. Check the following code where we have applied red color to the list items, but that style is only applied to the nodes which are part of the parent page, and the list items which are part of Shadow Root are not affected with this style.

      <div class="outer">
        <div id="welcomeMessage">Welcome to My World</div>
        <div class="normalTree">Sample List
        <ul>
            <li>Item 1</li>
            <li>Item 2</li>
        </ul>
        </div>
      </div>
      <style>
         div.outer li {  
            color: red;  
         } 
         div.outer{  
            border: solid 1px;  padding: 1em; 
         }
      </style>
      <script type="text/javascript">
          var shadowHost = document.querySelector("#welcomeMessage");
          var shadowRoot = shadowHost.webkitCreateShadowRoot();
          shadowRoot.innerHTML = ["<div class='shadowChild'>",
                                  "Shadow DOM offers us Encapsulation from",
                                  "<ul>",
                                  "<li>Scripts</li>",
                                  "<li>Styles</li>",
                                  "</ul>",
                                  "</div>"
                                  ].join(',').replace(/,/g,"");
      </script>
      

      You can see the code in action on Fiddle. This encapsulation applies even if we reverse the direction of traversal. Any styles which are defined inside the Shadow DOM does not affect the parent document and remains scoped to the Shadow Root only. Check this Fiddle for an example, where we apply the blue color to list items in Shadow DOM but the parent document’s list items are unaffected.

      There is however one notable exception here; Shadow DOM gives us the flexibility to style the Shadow Host, the DOM node which is holding the Shadow DOM. Ideally it lies outside the Shadow boundary and is not a part of Shadow Root, but using the @host rule, one can specify the styles that can be applied to Shadow Host as we have styled the welcome message in the example below.

      <div id="welcomeMessage">Welcome to My World</div>
      <script type="text/javascript">
        var shadowHost = document.querySelector("#welcomeMessage");
        var shadowRoot = shadowHost.webkitCreateShadowRoot();
        shadowRoot.innerHTML = ["<style>",
                                "@host{ ",
                                   "#welcomeMessage{ ",
                                      "font-size: 28px;",
                                      "font-family:cursive;",
                                      "font-weight:bold;",
                                   "}",
                                "}",
                                "</style>",
                                "<content select=''></content>"
                                ].join(',').replace(/,/g,"");
      </script>
      

      Check this Fiddle as we style the Shadow Host’s welcome message using the styles defined in Shadow DOM.

      Creating Style Hooks

      As a widget developer, I might want the user of my widget to be able to style certain elements. This is achievable by plugging a hole into the shadow boundary using custom pseudo elements. This is similar to how some browsers create style hooks for the developer to style some internal elements of a native widget. For example, to style the thumb and the track of the native slider you can use the ::-webkit-slider-thumb and ::webkit-slider-runnable-track as follows:

      
      input[type=range]{
          -webkit-appearance:none;
       }
       input[type=range]::-webkit-slider-thumb {
          -webkit-appearance:none;
          height:12px;
          width:12px;
          border-radius:6px;
          background:yellow;
          position:relative;
          top:-5px;
       }
       input[type=range]::-webkit-slider-runnable-track {
          background:red;
          height:2px;
       }
      
      

      Fork this Fiddle and apply your own styles to it!

      Event Re-Targeting

      If an event that originates from one of the nodes in Shadow DOM crosses the Shadow Boundary then it is re-targeted to refer to the Shadow Host in order to maintain encapsulation. Consider the following code:

      
      <input id="normalText" type="text" value="Normal DOM Text Node" />
      <div id="shadowHost"></div>
      <input id="shadowText" type="text" value="Shadow DOM Node" />
      <script type="text/javascript">
          var shadowHost = document.querySelector('#shadowHost');
          var shadowRoot = shadowHost.webkitCreateShadowRoot();
          var template = document.querySelector('template');
          shadowRoot.appendChild(template.content.cloneNode(true));
          template.remove();
          document.addEventListener('click', function(e) { 
                                       console.log(e.target.id + ' clicked!'); 
                                    });
      </script>
      

      It renders two text input elements, one via Normal DOM and another via Shadow DOM and then listens for a click event on the document. Now, when the second text input is clicked, the event is originated from inside Shadow DOM and when it crosses the Shadow Boundary, the event is modified to change the target element to Shadow Host’s <div> element instead of the <input> text input. We have also introduced a new <template> element here; this is conceptually similar to client-side templating solutions like Handlebars and Underscore but is not as evolved and lacks browser support. Having said that, using templates is the ideal way to write Shadow DOM rather than using script tags as has been done so far throughout this article.


      Separation of Concerns

      We already know that it’s always a good idea to separate actual content from presentation; Shadow DOM should not embed any content, which is to be finally shown to the user. Rather, the content should always be present on the original page and not hidden inside the Shadow DOM template. When the composition occurs, this content should then be projected into appropriate insertion points defined in the Shadow DOM’s template. Let’s rewrite the Hello World example, keeping in mind the above separation – a live example can be found on Fiddle.

      <div id="welcomeMessage">Welcome to Shadow DOM World</div>
      <script type="text/javascript">
          var shadowRoot = document.querySelector("#welcomeMessage").webkitCreateShadowRoot();
          var template = document.querySelector("template");
          shadowRoot.appendChild(template.content); 
          template.remove();
      </script>
      

      When the page is rendered, the content of the Shadow Host is projected into the place where the <content> element appears. This is a very simplistic example where <content> picks up everything inside the Shadow Host during composition. But it can very well be selective in picking the content from Shadow Host using the select attribute as shown below

      <div id="outer">How about some cool demo, eh ?
          <div class="cursiveButton">My Awesome Button</div>
      </div>
      <button>
        Fallback Content
      </button>
      <style>
      button{ 
         font-family: cursive;  
         font-size: 24px;
         color: red; 
      }
      </style>
      <script type="text/javascript">
          var shadowRoot = document.querySelector("#outer").webkitCreateShadowRoot(); 
          var template = document.querySelector("template"); 
          shadowRoot.appendChild(template.content.cloneNode(true));
          template.remove();
      </script>
      

      Check out the live demo and play with it to better understand the concept of insertion points and projections.


      Web Components

      As you may already know, Shadow DOM is a part of the Web Components Spec, which offers other neat features, like:

      1. Templates – are used to hold inert markup, which is to be used at a later point in time. By inert, we mean that all the images in the markup are not downloaded, scripts included are not present until the content of the template actually becomes a part of the page.
      2. Decorators – are used to apply the templates based on CSS Selectors and hence can be seen as decorating the existing elements by enhancing their presentation.
      3. HTML Imports – provides us with the capability to reuse other HTML documents in our document without having to explicitly make XHR calls and write event handlers for it.
      4. Custom Elements – allows us to define new HTML element types which can then be used declaratively in the markup. For example, if you want to create your own navigation widget, you define your navigation element, inheriting from HTMLElement and providing certain life-cycle callbacks which implement certain events like construction, change, destruction of the widget and simply use that widget in your markup as <myAwesomeNavigation attr1="value1"..></myAwesomeNavigation>. So custom elements essentially give us a way to bundle all the Shadow DOM magic, hiding the internal details and packages everything together.

      I wont babble much about other aspects of the Web Components Spec in this article but it would do us good to remember that together they enable us to create re-usable UI widgets which are portable across browsers in look and feel and fully encapsulated by all the scripts and styles of the consuming page.


      Conclusion

      The Web Components Spec is a work in progress and the sample code included which works today may not work on a later release. As an example, earlier texts on this subject use the webkitShadowRoot() method which no longer works; Instead use createWebkitShadowRoot() to create a Shadow Root. So if you want to use this to create some cool demos using Shadow DOM, it’s always best to refer to the spec for details.

      Currently, only Chrome and Opera supports it so I would be wary about including any Shadow DOM on my production instance, but with Google coming out with Polymer which is built on top of Web Components and Polyfills coming out to support Shadow DOM natively, this is surely something that every web developer must get his hands dirty with.

      You can also stay updated with the latest happenings on Shadow DOM by following this Google+ Channel. Also checkout the Shadow DOM Visualizer tool, which helps you to visualize how Shadow DOM renders in the browser.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. Easy Ways to Contribute to Open-source Projects

      When the jQuery project first started, I remember how passionate the team was about helping developers use the jQuery JavaScript library. It was a labor of love with all of us putting in countless numbers of hours, day and night, to help grow the project and the developer community. And we did those for free because we just loved doing it. But as the project grew, so did the expectations from the community in terms of features and support. And this is where most open-source efforts fail to scale.

      I think most developers that put out OSS software do it for altruistic reasons wanting to give back to the community something that may solve a critical problem.

      As community needs grow, you need to find ways to have more time to focus on features. You can do this by growing your team but that’s not always a solution. On the jQuery project, we increased team size and delegated work but even so, being a volunteer-based effort meant the project was reliant on other people’s availability. And with all of us having full-time jobs and many with family responsibilities, I can say that we managed to accomplish a lot with very little availability.

      The other option that manifested was the ability to fund time to focus on working on specific tasks. This typically came in the form of sponsorships from name-brand companies that had made substantial internal investments into jQuery and wanted the project to succeed. This actually worked well because it allowed team members to be able to specifically focus on meeting the community needs and focus their abilities on the tough areas that required a lot of dedicated attention.

      Now please don’t think this just came about overnight. It took a long time before anyone wanted to contribute to the project and proving the value of the effort was the critical component to that. jQuery is an important part of many sites and products but that following developed over years of hard work and consistency and is not the norm for most OSS projects. And most OSS projects will never enjoy the level of success and notoriety jQuery has simply because of timing or even being “too niche”.

      And there’s absolutely nothing wrong with that. I think most developers that put out OSS software do it for altruistic reasons wanting to give back to the community something that may solve a critical problem. So how do these projects get a leg up like the jQuery project did?

      Let’s explore this.


      OSS Consumers vs. Contributors

      I’ve not met someone (both offline and online) who hasn’t used some open-source software. That’s a pretty big deal because it shows that OSS is everywhere. Developers rely on it to start-up their next great idea. Companies leverage it to lower costs. And governments use it to ensure their meeting the needs of their communities. To say it’s pervasive would be an understatement.

      The one thing I’ve felt for a long time, though, is that there’s a definite imbalance between consumers and contributors. The ease with which someone can grab a piece of OSS software and run with it due to flexible licensing and little to no cost makes it incredibly easy to forget that someone out there is actually writing and supporting that software. If you simply consume without considering the time, effort and costs involved in that piece of software, there’s a strong likelihood that down the road you’ll be impacted when the project fails. The road to OSS is littered with failed and abandoned projects created by developers with all the right intentions but just didn’t have the resources to keep it going.


      How to Give Back

      It’s not to say that you need to go all-in like Facebook did with PHP but there are many ways of helping a project from which you’ve taken something that’s valuable to you and your business. Some low hanging fruit are:

      • Contribute code – Most projects use GitHub which makes creating pull requests insanely easy
      • Contribute time – Projects are always looking for people to help with documentation, support and evangelism
      • Write a blog post – Easy enough to write something that makes using a tool easier for others
      • Ask your employer for time – If you’re using a piece of OSS software at work, ask your employer for company time to contribute back
      • Ask your employer to donate back code – Along the same lines, if you’re extending functionality consider contributing it back under the same license of the project

      Many projects have pages similar to this that explain specifically how to contribute.

      If for whatever reason you can’t offer any of these, you should consider helping to fund some of these efforts. “How?” you ask.


      Donating Online

      There have been platforms springing up that are designed to solve this problem and we’re going to take a look at two of the most populars ones.

      Bountysource – The OSS Projects Funding Platform

      bountysource-logo

      Recently, I came across a fundraiser for RVM (Ruby Version Manager). If you’ve ever coded in Ruby on Rails, then I’m pretty sure you know how important RVM is. Unfortunately, it’s main sponsor was ending its support and the project needed to find another sponsor so they took to a novel site called Bountysource which aims to provide a funding platform for open-source software.

      bounty-rvm

      I found this totally awesome because there really wasn’t a resource like this for the jQuery project (or MooTools, Prototype, et al) that could allow a project to spin up a fundraising page with all the tools to collect donations. And of course, it allows individuals to browser projects they’d like to help fund and donate via PayPal or Google Wallet.

      What really impressed me is that fact that a project can list out the things they want to accomplish and through crowdsourcing, the community can help to fund the completion of the specific features through developer payouts (called a “bounty”). So say that you really wanted $.Deferred functionality in Zepto.js. You could contribute to the feature request to entice the community to implement and once it’s done, the bounty would be paid out to the person(s) who did it.

      bounty-zepto

      The service addresses the need of the project, even to the point of breaking down the bounties to specific tasks and values but also allows the community to decide what’s important and fund the development of that feature. It’s a bit of a KickStarter for open-source. Very cool.

      Gittip – Crowdfunding People Who Inspire You

      gittip-logo

      Gittip is a service I found out about because of John Resig. He’s been a real advocate of the service and that says a lot.

      gittip-home

      To quote John:

      I saw a great opportunity for the development team at Khan Academy to give back to the Open Source community in ways that were not just code-related.

      It’s very different from Bountysource in that it’s meant to offer small weekly cash gifts to individuals that you feel are providing you a value. You can give any amount you want up to $100 per week. This is actually a great resource for those single-man projects where the lone coder is adding features, answering support emails and working the community. It might seem inconsequential but even donating five dollars per week to that developer may be what he/she needs to ensure they know their work is appreciated.

      There are over 650 communities listed on Gittip and choosing one will display all of the top givers and receivers:

      gittip-js

      This also allows you to drill-down into individual profile pages to allow you to contribute to some who inspires you:

      gittip-resig

      And in keeping inline with its OSS ethos, Gittip even allows you to checkout its source code via its Github repo.


      More “Do” than “How”

      The point of this article is to drive home the importance of contributing back to open-source. If you’re a consumer, then you should seriously evaluate how valuable that library or tool is to you and figure out how to support it. If the project isn’t on Bountysource or Gittip, why not reach out to the project owner and ask them to join so you can donate.

      And just because you may not be interested in contributing code doesn’t mean you can’t leverage other skills to help a project grow. In my opinion, the single biggest need of an open-source project are people who know how to work with a community. Soft skills are so important and from my experiences, sorely lacking.

      The main thing is that there really is no excuse not to contribute back when you find something valuable. Just because it’s “free” doesn’t mean that a lot of investment wasn’t placed into it and if you don’t support it, it may just go away some day.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. WebGL With Three.js: Shaders

      3D graphics in the browser have been a topic of interest since its introduction. But if you were to create your apps using plain old WebGL, it would take ages. Recently, some really useful libraries have come available. Three.js is one of the most popular, and in this series I will show you how to make the best use of it, to create stunning 3D experiences for your users.

      I do expect you to have a basic understanding of 3D space before you start reading this tutorial, as I won’t be explaining things like coordinates, vectors, etc.


      A Word About Shaders

      If you already know what shaders are, you may skip this step. Shaders are basically programs written in GLSL (Graphics Layer Scripting Language), that are executed on the GPU. This makes them extremely useful, as we can take some work from the CPU and put it on the GPU to increase performance. There are two kinds: vertex and fragment shaders. Vertex shaders are used to modify the structure of the object (move the vertices), and fragment shaders make changes to the pixels that are being drawn.


      Step 1: Vertex Shader

      We will start with the simpler one. This shader will modify the placement of the vectors in the mesh, resulting in moving faces. Insert this code into <head> of your app:

      <script id="cubeVertexShader" type="x-shader/x-vertex">
      	uniform float time;
      	varying vec2 vUv;
      
      	void main() {
      		vUv = uv;
      		vec3 newPosition = position + normal * vec3(sin(time * 0.2) * 3.0);
      		gl_Position = projectionMatrix <i> modelViewMatrix </i> vec4(newPosition, 1.0);
      	}
      </script>
      

      The type attribute of this script won’t be understood by the browser, so it will not get executed (we will pass its contents to the Three.js material later). In the first two lines we are defining two variables. The first one is uniform float time. Uniforms are passed to both vertex and fragment shaders. Next, there is varying vec2 vUv. Varyings are the interface between the vertex and the fragment shader. time will hold the time in milliseconds since the app was started, which we will use to calculate new positions of vertexes. In vUv we will store the UV (texture vector) of each vertex, so we can use it in the fragment shader.

      Next, there is the void main() declaration. All shaders must have this function. In here we are passing the UV of the vertex to our vUv and calculating the vertex’s new position. Finally, we set the gl_Position, which in fact sets the position of the vertex. But also, we have to multiply the position calculated earlier by the projectionMatrix and modelViewMatrix, two matrices that Three.js supplies to us. This is necessary because if we don’t do this, the GPU will not consider the point from which we are looking at the vertex. Now let’s move to the fragment shader.


      Step 2: Fragment Shader

      Now this is the place where all the magic happens. Fragment shaders are responsible for all of those good looking games. The one we will use is pretty simple, so don’t expect to see a scene from Crysis 3 after using it. Insert the following code under your vertex shader:

      <script id="cubeFragmentShader" type="x-shader/x-fragment">
      		uniform float time;
      		varying vec2 vUv;
      
      		void main() {
      			vec2 position = -1.0 + 2.0 * vUv;
      
      			float red = abs(sin(position.x * position.y + time / 5.0));
      			float green = abs(sin(position.x * position.y + time / 4.0));
      			float blue = abs(sin(position.x * position.y + time / 3.0 ));
      			gl_FragColor = vec4(red, green, blue, 1.0);
      		}
      	</script>
      

      As you can see at the top of the shader, there are our two variables again. You have to keep in mind that all variables you use (except the ones from Three.js) must be defined in each shader they are used in.

      In the void main() function, we are calculating the colors based on the time and UV of the fragment (fragment shaders operate on fragments, which are composed from vertices, so the values of varying variables are interpolated in the fragment shader). Feel free to mess with those numbers and functions (just remember that the color values must be positive).

      Finally, we are setting the gl_FragColor variable which sets the fragment’s color.

      If you open your browser now, nothing will change, because we have to change the material of the object so it uses shaders.


      Step 3: THREE.ShaderMaterial

      This special material is used whenever we need to use shaders. Let’s change the material of the object that we attached to our model in the previous part of this series. First, define the uniforms array which will be used to pass variables to the shaders:

      var uniforms = {
      	time: { type: "f", value: 0 },
      	resolution: { type: "v2", value: new THREE.Vector2 },
      	texture: { type: "t", value: THREE.ImageUtils.loadTexture('./box.png') }
      };
      

      Next, in the loader.load define the item‘s material and use it:

      var itemMaterial = new THREE.ShaderMaterial({
      	uniforms: uniforms,
      	vertexShader: document.getElementById('cubeVertexShader').innerHTML,
      	fragmentShader: document.getElementById('cubeFragmentShader').innerHTML
      });
      item = new THREE.Mesh(new THREE.CubeGeometry(100, 10, 10), itemMaterial);
      

      Now, if you open the browser, you should see that the red beam changed its colors:

      shaders_result_not_moving

      But the colors are not changing, and the mesh is not animated either. To change that, we have to update the time variable in the shaders each time a frame is drawn. Go to the render function and add this line after the clock.getDelta() call:

      uniforms.time.value += delta * 10;
      

      Now if you open the browser, you should see a nicely animated and colorful object:

      shaders_animated_and_colorful

      A Word About Performance

      If we were to create such a texture effect using, for example, HTML5 Canvas, the process would take too much of the CPU’s cycles, resulting in lags. But all shaders are executed on the GPU, which is optimized for all operations on graphics and is focused only on them. Separating graphic and non-graphic calculations is the key to a good performing app.

      If you want to create something real using WebGL, allow me to assure you, that you will have to move as much work as possible to the GPU, to make your application smooth and responsive.


      Conclusion

      As you can see, using Three.js allows us to create 3D graphics in the browser very easily, and the results are actually pretty good. But, they can be even better, take a look at these examples from Three.js’s site:

      With enough time, a creative mind and Three.js, you can create amazing apps like those too. I will be more than happy to see your Three.js creations. Thanks for reading.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. Statamic 101

      Statamic is a modern PHP CMS which really makes an effort to be easy and intuitive to use. From its flat-file design to its use of technologies, like markdown and Yaml, you can accomplish an outstanding amount of work without writing any code at all.

      In this article we will take a look at the process from installation to setting up a basic portfolio.

      Having a flat-file design, setup is as simple as extracting the zip file you’ll download from their site. There is no database involved, all the content and settings are stored locally in a host of different files, this also means you have automatic backups and versioning on all of your content, if you use something like GIT.

      With the contents extracted, let's take a look at Statamic’s structure.


      The File Structure

      There are more or less five different folders you will most likely be interacting with, and they are:

      • _config is where all your settings are held
      • _content is where you will put your Markdown files
      • _add-ons is for Statamic add-ons
      • _themes is where you build your theme
      • assets is where you can stick resources for your site

      Besides these, you have the following four folders that you probably won't touch directly:

      • _app – Statamic’s own source code
      • _cache – Where Statamic caches all your content
      • _logs – Where Statamic will store your logs
      • admin – The Statamic admin panel

      But the first step in every Statamic site is to configure its options.


      Configuration

      All the configuration files are inside the _config folder like we just saw, the main file you should take a look at is the settings.yaml.

      If you are new to Yaml, then all you really need to know, is that it's a data format similar to JSON except that it's meant to be a more human-readable format. It accomplishes this by not requiring any separating characters like semi-colons or quotation marks, instead it get's its structure from placement and indentation.

      The settings.yaml file is really well documented so you shouldn't have a problem filling it out, some of the options you will probably want to look at are the following:

      _license_key: Enter your License Key
      _site_name: My Portfolio
      _site_url: http://localhost:7000
      _theme: portfolio
      _taxonomy: 
         - language
      _log_enabled: true
      _cookies.secret_key: Some Random Key
      

      Most of these are pretty straight forward, like setting the license key, your site's name and URL. The theme option sets which theme folder to load. We will get into this in a moment, but a theme is essentially the place where you specify how the different pages on your site will work. We will be creating our own theme so you can name it whatever you want, I chose ‘portfolio’.

      The next option is an array called taxonomy, if you have ever used something like WordPress, then you should know what this is for, basically it allows you to add a setting or 'type' to each post, which you can then use these taxonomies to filter your content and create custom pages for these groupings.

      I am just adding one taxonomy; the language taxonomy, because in our example portfolio we are going to specify each work’s programming languages. You don’t need to create a taxonomy for each custom property, we are going to want other things in our portfolio, like links and descriptions. A taxonomy is for fields that multiple entries have in common, and for fields that you may want to create a custom page for.

      The log_enabled setting turns on logging, so you can view problems which come up from the admin panel, they will be stored in the _logs folder we saw earlier. Finally the last option I mentioned is the secret key used to encrypt the cookie.

      This file can now be saved out, but before we move onto content, let's take a moment to setup the portfolio template so we can see what we are doing.


      Theme Basics

      The template is a specific view for a single page.

      Like most modern frameworks, when you load a page, you can build it up from multiple reusable components. A page in Statamic is made up of a layout a template and a content file. Both the layout files and templates can optionally also be made of even more pieces called partials.

      The layout is the outer shell in which your template will be placed; this is usually used to hold the boilerplate HTML code like the head section, and as-well as the basic body that all the pages using this layout will need, like adding common libraries at the bottom of your file.

      The template is a specific view for a single page. Like you can have a home page template, a contact page template, etc.. You don't need to create on per page, but I would say one per type of page.

      In these templates you have the ability to use variables stored in the actual content files, so say you need a page which displays an index of books you are reading, and then another page to display a list of shows you are watching; instead of replicating most of the code for each one, you can create one template for displaying a list of objects, and then pull in the specifics of which list to retrieve from the content file itself.

      The content file – like its name suggests – is the actual resource being displayed, this can range from things like an actual unique web page, to a single blog entry. We will get to these in more details in a moment.

      Now instead of manually creating all these different components, Statamic provides a sort of starter template, giving you a basic structure to get started. You can download the theme folder from here.

      Just place the entire folder into the _themes directory, and rename it to portfolio (as that's the theme name we declared in the settings file). You also need to rename the kindling.js file from the js folder and the kindling.css file from the css directory, to portfolio.js and portfolio.css respectively, as their is a special tag to pull these in automatically.

      That's all the setup we need now, but to get a better idea of what I was talking about regarding the layout/template, let's take a look at those files. To begin with open up the file named default.html from the layouts folder, this corresponds to the default layout as you may have guessed.

      <!DOCTYPE html>
      <html lang="en">
          <head>
              <meta charset="utf-8" />
              <title>{{ _site_name }}</title>
              <link rel="stylesheet" href="{{ theme:css }}">
          </head>
          <body>
      
              {{ layout_content }}
      
              <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
              <script src="{{ theme:js }}"></script>
      
          </body>
      </html>
      

      Like I mentioned earlier, the layout is a good place to put code that is required on multiple pages (or templates rather), which is why the default layout in this file just contains the basic outline of an HTML file. Now we haven't really talked about it yet, but Statamic comes with its own templating engine, which is fairly easy to pick up, you basically just place a tag where you want something to be inserted similar to Handlebars if you are familiar.

      This layout contains a couple of tags which I thought I would go through, the first of which is _site_name. This tag actually refers to the property we set up inside of the settings.yaml file. You will find this convention all throughout Statamic, you can set yaml options either globally like this, or even on a per-file basis, you can then get these options just by placing a tag with their names into your templates.

      Helpers in Statamic are more like independent modules.

      The next tag, which actually comes up twice is the theme tag. Helpers in Statamic are more like independent modules, so they can have multiple different functions attached to the same name; you access the individual functions with a colon and then the name of the command you want.

      The theme tag is all about loading in resources specific to this theme, it can be used to pull in things like scripts and stylesheets, but also things like images and partials. It's a helper function that basically allows you to just provide the name of the resource you want and it will fill in the path to the current templates directory. So for instance if you were to write:

      {{ theme:js src="underscore.js" }}
      

      It would replace that with a link to a file named underscore.js inside of the current theme’s js folder. By default if no src parameter is set for the js or css command, it will assume you are referring to a js or css file with the name of the current theme, which is why we renamed those files to match; it's just a matter of convenience so we don't need to specify them and it cleans up the source a little bit.

      The next tag that comes up is {{ layout_content }}; this is similar to yield in other templating engines, and it basically signifies where the inner template should be inserted.

      The last thing I want to do in this file is remove the link to jQuery, just because I won't be using it (if you will then you can of-course leave it).

      Next let's move onto the default template file (templates/default.html), it should be blank. For illustrations sake, let's just add a tag called {{content}} which just inserts the contents of the current page being loaded.

      So to recap when you goto a page it will first load the layout file, and then wherever the {{layout_content}} tag is placed this template will get inserted. This template will then just output whatever the current page has inside.

      With that done, save out these files and let's move onto content.


      The Content

      Content in Statamic is specified in markdown files by default, and the default file which is loaded is called page.md. What I mean by this is that the same way standard web server will load index.html if no file was specified, Statamic will load page.md.

      It's also worth noting that routes, or URL links in your site will be defined by the _content directory. So for example if you create a folder named 'demo' inside of the _content directory, and in it place a file named 'link.md' this will correspond to the URL /demo/link; and if you place a page.md file inside, it will be loaded if you navigate to /demo/ since it is the default file name.

      Statamic comes with some demo content, but you can just delete everything inside the _content directory for this example (or move it aside for now).

      Let's start with a basic home page, so at the root of the _content directory, create a file named page.md with the following:

      ---
      title: Home
      ---
      
      # Welcome to the {{title}} Page
      

      All content files are basically split into two sections, the Yaml front-matter and the contents. The top part (between the dashed lines) is where you can put standard Yaml specific to this file, and is a good way for setting options to adjust your template files. The second part is the markdown area, where you put the contents of the actual page. You can use standard markdown as-well as Statamic helper tags.

      This page will load with the default layout and template files we just setup, but if you want it to use a different one, you can specify these as options in the Yaml section at the top using _layout and _template respectively.

      If you create a server at the root of your Statamic directory:

      php -S localhost:7000
      

      and then navigate to http://localhost:7000 in your browser you should see the H1 tag with our welcome message.

      This is all you need to know to create pages in Statamic, and if you are building a fairly static site, this would be enough. But in a lot of sites we need to be able to add dynamic data, which can take the form of blog posts, shop items, or in our case portfolio works.


      Entries

      If you recall there is no database in Statamic, so these kinds of entries are stored in markdown files just like the page we just built, although a couple of things were done to subtly introduce multiple features to optimize things and to make it work in the admin.

      First off you can name the files with a special date format so they can be sorted and filtered by date. You do this by pre-pending the title with a year-month-day pattern, so say you want to create a post named 'foobar' you would name it something like:

      2013-09-15-foobar.md
      

      Inside you would put all the posts settings inside the front-matter section for use in the template, and then any content underneath; just like in a page.

      Now this is pretty cool, but it's the equivalent of manually entering posts into a database of a traditional system; there is another option.

      Statamic comes bundled with a really nice admin, which can do all this for you, but in order to get it setup we need to tell it which fields this type of entry is supposed to have. This is done in a file appropriately named fields.yaml.

      So for our example let's create a folder inside the _content directory named works, and inside the works folder let's create a file named fields.yaml. Inside the fields.yaml file we need to specify which properties our 'entries' will contain and the individual types for each of these settings.

      You can either specify your fieldset (the list of fields) in the _config/fieldsets/ directory and pull in a definition, or you can just enter the definition here (or you can do both to extend an existing definition). For our simple example I am just going to put the definition here since we won't be reusing it anywhere:

      type: date
      fields:
       language:
         type: tags
         display: Programming Language
         required: true
      
       description:
          type: text
          display: Description
          required: false
      
       link:
          type: text
          display: Link
          required: true
      
       content:
          type: hidden
      

      The first property just tells Statamic that we want these entry files to have a date property and to be named appropriately. Next we open up a YAML object named fields containing all our work entry's properties.

      The first is the language field, which if you remember is the taxonomy we created in the settings.yaml. Inside each property we need to specify its type (or it defaults to a text box) its display text (which will default to the properties name) and whether it is required. There are other options you can set as-well like instructions or the default value, which you can view more information about here, besides for these settings different field types can have their own custom options.

      For the language input I set it to use the tag type, which basically allows you to set multiple tags for this option, it's just a different type of input for entering its value in the admin. You can view all the different fieldtypes here or from the official cheat sheet under 'Fieldtypes'.

      The description and link are pretty much the same, they will both be text boxes except one will be required and one won't be. Besides the fields you specify all entries will come with a title and content field. We don't really want a content field in our works they will be more like links, so I just set it to hidden.

      The last step before we go to the admin, is to create a page.md file inside the works directory. This isn't really required but the admin will attempt to get the title of this entry type from here so it's a good idea to just place it. So create a page.md file inside the works folder with just the title set to 'Works':

      ---
      title: Works
      ---  
      

      The Admin

      To get into the admin we need to first create a user; again this is a simple yaml file inside of the config folder. The name of the file is the username you will use to login, and inside you configure the user's details and password.

      So let's create a new user with a username of editor, again we do this by creating a file called 'editor.yaml' inside of the _config/users/ folder. Insert the following data (except with your info):

      --- 
      first_name: Gabriel
      last_name: Manricks
      roles: [admin]
      email: gmanricks@gmail.com
      password: password
      ---
      
      The Editor of this Portfolio
      

      Most of these columns are pretty straight forward and I don't think they require any explanation. The only field worth mentioning is the roles setting. Currently admin is the only option available, but in the future this will be where you would be able to adjust who can edit what.

      It's also worth mentioning that the password will not stay in plain-text. After the first login, Statamic will hash the password along with a salt and include those here instead.

      Everything after the dashed lines will just be stored as the content for this user, and can be used as a sort of bio for them.

      Now save this file, and if your web server is still running, navigate to /admin in your browser. This will open up the login console where you can enter these properties. Like I mentioned the first time you login you will need to do this twice, once to hash the password, and the second time to actually login.

      Admin Login

      The Statamic Login

      Once in you will see a list of our pages, included is our home page as-well as the 'Works' entry type. Let's take a look at what our fields declaration did for us; click on the Create link inside of the 'Works' bar.

      Pages Admin

      You should see a nice form which includes all the fields we specified along with the tite, for this demos sake, just add a few posts.

      Demo Post

      With some posts stored, we have completed round one; you now know how to create pages, themes, users, and entries, it's a great first step. But there is alot more Statamic has to offer.


      The Templating Engine

      Having some posts created is nice, but what would be better is if we could actually display them on a page. For this we will need to edit the default template.

      This will be our first real interaction with the included templating engine, but not to worry, Statamic's intuitive design makes it almost 'obvious' to pick up.

      To view a full list of the available tags you can take a look at the official doc page on the matter. But all we really need in our example is the entries tag, which is used to pull in entries from a specific folder in the _content directory. There are a lot of optional properties, allowing you to filter by date, or conditions like taxonomies or even standard properties. We are going to keep it simple and just list the properties by date (which is the default).

      Here is the complete new default template (templates/default.html):

      <h1>Portfolio</h1>
      
      <table>
       {{ entries:listing folder="works" }}
           <tr>
               <td class="lang"><p>{{ language }}</p></td>
               <td class="work">
                   <a href="{{ link }}">
                       <span class="title">{{ title }} - </span>
                       <span class="desc">{{ description }}</span>
                   </a>
               </td>
           </tr>
       {{ /entries:listing }}
      </table>
      

      In this code we are creating a table and just looping through all posts in the 'works' directory. These kind of block tags, where you place more HTML inside, basically assign new placeholders. Besides for providing access to things like all the post's attributes, you also get special helper variables which can tell you things like the current index, or whether this is the first or last post. We won't be using any of those variables, all we need is to display the title / language / description and link. However if you load up the page in your browser, you will probably realize that instead of showing the language it just says "Array".

      This is because we set this property to be of type tag, which means it could hold more than one language, so even though you may have only put one language, it is still being stored in an array. Luckily besides for these tag helpers, Statamic comes with modifiers.


      Modifiers

      To finish off this guide, let's take a look at a few modifiers which will allow us to make this page even better.

      The first and biggest problem is making the language show up. If you take a look at the following cheat sheet, all the way at the bottom left, you will see a section named List Shortcuts. While not technically being modifiers, Statamic allows you to append these words to the end of a list variable, and it will instead return a string representation. The one I want to use in this situation is the standard _list helper. What this will do is separate multiple values in the array with a comma and space, and is what we would want in our situation.

      To try it out, replace the {{ language }} tag to {{ language_list }}. Refreshing your browser it should be displaying the languages correctly now.

      Next let's add a modifier to the title to make it all uppercase. If you have ever used something like the smarty templating engine, then it works the same way. You add a pipe to the end of the variable name and then add a modifier. In our example you just need to replace the call to {{ title }} with {{ title|upper }} and these are chainable so you can keep adding pipes indefinitely.

      Now let's just add some CSS to style everything up (remember this goes in the css/portfolio.css file:

      body { background: #FAFAF5; }
      
      h1 {
       font: 800 64px 'Raleway', sans-serif;
       margin-bottom: 28px;
      }
      
      table { font: 15px 'Coustard', serif; }
      
      td { padding: 10px 10px 0 10px; }
      p { margin-bottom: 15px; }
      
      .lang p {
       background: #CA9F53;
       color: #FFF;
       padding: 3px 5px;
       text-align: right;
      }
      
      .work { text-align:left; }
      .work a{
       border-bottom: 1px solid #000;
       text-decoration: none;
      }
      
      .title {
       font-weight: 600;
       color: #000;
      }
      
      .desc { color: #666; }
      

      And these two fonts are from Google Fonts, so you will need to add the following link at the top of your default layout file:

      <!DOCTYPE html>
      <html lang="en">
      <head>
       <meta charset="utf-8" />
       <title>{{ _site_name }}</title>
       <link href='http://fonts.googleapis.com/css?family=Coustard|Raleway:800' rel='stylesheet' type='text/css'>
       <link rel="stylesheet" href="{{ theme:css }}">
      </head>
      <body>
      
       {{ layout_content }}
      
       <script src="{{ theme:js }}"></script>
      
      </body>
      </html>
      

      If everything worked out you should see the following page (except with the works you added)

      The Demo

      Conclusion

      Where I think this will thrive is as a blogging platform or CMS.

      In this article we have went through the entire process from installing the framework, to setting everything up, creating a new entry type, and building a custom theme. It's a lot to do, and it's only possible because of how easy Statamic makes things.

      We have seen alot of functionality already and we haven't even touched on creating your own modules, and extending Statamic with PHP, but I think the most amazing thing is we haven’t even written a single line of PHP in this entire article! And that is something to brag about.

      So I think the main question people might have is, should I use it, or what should this replace in my current repertoire? It's important to gauge what Statamic is for. If you are building a new Startup and need the full flexibility of a full fledged framework, I am sure you would be able to get it running in Statamic, but it would be alot of custom code, which may defeat the purpose. Where I think this will thrive is as a blogging platform or CMS.

      Coming from a background in WordPress, this feels like a direct predecessor, in that it follows a-lot of the same conventions in theory, but they are all implemented in a much smarter way, in that comparing the amount of code required in each becomes a joke. Moving forward, Statamic has an incredible API for building custom tags, hooks, new fieldtypes and more, and you can imagine Statamic makes it as lean and simple to do as you might have come to expect.

      I hope you enjoyed this article, if you have any questions feel free to ask me below, on twitter @gabrielmanricks or on the Nettuts+ IRC channel on freenode (#nettuts).

       

      0 Comments

      Leave a comment › Posted in: Daily

  • Page 3 of 18 pages  < 1 2 3 4 5 >  Last ›
  • Browse the Blog

    Syndicate

    governing-bruise