<?xml version="1.0"?>
<News hasArchived="true" page="8619" pageCount="10722" pageSize="10" timestamp="Sat, 11 Jul 2026 04:21:12 -0400" url="https://my3.my.umbc.edu/posts.xml?page=8619">
<NewsItem contentIssues="true" id="31315" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31315">
<Title>How to Get Your Web Development Projects Off to a Good Start</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><a href="http://sixrevisions.com/project-management/web-development-kickoff-meeting/" rel="nofollow external" class="bo"><img src="http://cdn.sixrevisions.com/0348-01_web_development_kickoff_meeting_thumbnail.jpg" width="550" height="200" alt="How to Get Your Web Development Projects Off to a Good Start" style="max-width: 100%; height: auto;"></a></p>
    <p>If you’re anything like my team, you probably want to dive right in head first into a web development project as soon as you possibly can. Because we love our jobs — we’re all very passionate about it.</p>
    <p>We’re eager to get started without having to deal with the "boring parts" and we have a laser-beam focus towards the more enjoyable, fun aspects of web development — coding, setting up servers, designing the user interface, you know, the good stuff.</p>
    <p></p>
    <p>Early in my web development agency’s history, this is how we worked: The moment we returned from a project’s contract signing, <a href="http://sixrevisions.com/category/photoshop/" title="Photoshop articles on Six Revisions" rel="nofollow external" class="bo">Photoshop</a> would fly open, databases would be fumbled together, and code would be quickly written. We couldn’t wait to get started with production.</p>
    <p>And when that happens, <a href="http://sixrevisions.com/project-management/website-architecture/" title="The Secret to Building Large Websites: Website Architecture" rel="nofollow external" class="bo">proper planning</a> goes out the window.</p>
    <p>The result of insufficient planning and coordination? A project of any size and scope, big or small, ended up becoming a mess quite quickly.</p>
    <h3>The Secret to a Good Start: Project Kickoff Meetings</h3>
    <p>To get web development projects off to a good start, we now realize that effective <strong>kickoff meetings</strong> are essential.</p>
    <h3>What is a Kickoff Meeting?</h3>
    <p>An important component of planning your web development project is the <a href="http://en.wikipedia.org/wiki/Kickoff_meeting" rel="nofollow external" class="bo">kickoff meeting</a>.</p>
    <p>The project kickoff meeting is the initial meeting consisting of the project’s team and the client/decision-makers. It involves getting your team and all the decision-makers in a room to hash out the details about the project.</p>
    <p>This meeting is important to web development projects because:</p>
    <ul>
    <li>It familiarizes all the individuals involved in the project with each other</li>
    <li>It extracts important details from the appropriate individuals to avoid <a href="http://en.wikipedia.org/wiki/Information_silo" rel="nofollow external" class="bo">information silos</a>
    </li>
    <li>It gives everyone clarity about the core objectives of the project</li>
    <li>It gets everyone on the same page</li>
    <li>It promotes active communication lines</li>
    <li>It gets the project off to a great start</li>
    </ul>
    <p>Let me share with you how I prepare and conduct my company’s web development project kickoff meetings. I promise that you and your client will have a better experience and will come out with a better product if you install a good kickoff meeting as part of your web development process.</p>
    <h3>The Project Kickoff Meeting Outline</h3>
    <p>Here is a brief digest of our project kickoff meeting structure:</p>
    <p><img src="http://cdn.sixrevisions.com/0348-12_web_development_kickoff_meeting_kickoffoutline.png" width="550" height="546" style="max-width: 100%; height: auto;"></p>
    <p>I’ll discuss each of these items below.</p>
    <h3>Before The Kickoff Meeting</h3>
    <p>I suggest having a template for your kickoff meetings to promote efficiency and to ensure that you get the most value out of the meeting.</p>
    <p>It’s nice to have a template guiding you for all the things you’re going to need from the client. You can print your template and then immediately start filling it up with information you already know well before the meeting’s date.</p>
    <p>If you do several types of development (e.g. <a href="http://sixrevisions.com/web-applications/building-mobile-web-apps-the-right-way-tips-and-techniques/" title="Building Mobile Web Apps the Right Way: Tips and Techniques" rel="nofollow external" class="bo">mobile app development</a>, web app development, <a href="http://sixrevisions.com/project-management/tips-for-creating-an-excellent-e-commerce-website/" rel="nofollow external" class="bo">e-commerce site development</a>, etc.) you may have to create a few different versions of your kickoff meeting template.</p>
    <p>To help you get started, you can <a href="http://cdn.sixrevisions.com/0348-13_web_development_kickoff_meeting_template.pdf" rel="nofollow external" class="bo">download my kickoff meeting template</a> for web development projects. It’s a 7-page PDF document. It’s simple, but it serves as a fantastic way to start your projects off. You can look over this template and see exactly what you’ll need.</p>
    <p><a href="http://cdn.sixrevisions.com/0348-13_web_development_kickoff_meeting_template.pdf" rel="nofollow external" class="bo"><img src="http://cdn.sixrevisions.com/0348-03_web_development_kickoff_meeting_downloadwebdevchecklist.jpg" width="550" height="250" style="max-width: 100%; height: auto;"></a></p>
    <p>Be sure and read through the template and add to it based on your own business processes, workflow, and custom requirements.</p>
    <h4>Gather Basic Internal Information</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-04_web_development_kickoff_meeting_prekickoffmeeting.jpg" width="550" height="712" style="max-width: 100%; height: auto;"></p>
    <p>The first thing you should do before getting everyone together for the kickoff meeting is to gather basic information about the project.</p>
    <p>On your end, write down basic project details such as:</p>
    <ul>
    <li>The project’s primary goals</li>
    <li>Your project manager’s contact information</li>
    <li>Secondary contact’s information in case the project manager is unavailable</li>
    </ul>
    <h4>Gather Basic Client Information</h4>
    <p>We are going to need technical information from the client such as server info, domain information, analytics data, previous SEO campaigns, and so forth.</p>
    <p>Give your client a chance to get some of their information together before your kickoff meeting and send them a quick worksheet to fill out plenty of time before your first kickoff meeting sit down.</p>
    <p>If enough time is given (1 week is enough time in my experience) it’s a good litmus test on how responsive and communicative your client is going to be throughout the web development project. Of course, this isn’t always guaranteed, but I like to use it as an indicator.</p>
    <p>You should now be ready for the kickoff meeting after this.</p>
    <p>Before getting into the specifics of the kickoff meeting, I’d like to first share some basic tips about meetings in general.</p>
    <h3>Fundamental Kickoff Meeting Tips</h3>
    <p>Your project kickoff meeting is an exciting time. Deposits have been paid, and the client is ready to get started on their project ASAP.</p>
    <p>I find the <strong>more prepared</strong> I am for the kickoff meeting, the more likely the client will follow my lead and trust my judgment during the meeting as well as throughout the lifecycle of the project.</p>
    <p><img src="http://cdn.sixrevisions.com/0348-15_web_development_kickoff_meeting_prep.png" alt="" width="550" height="550" style="max-width: 100%; height: auto;"></p>
    <p>So, how can we guarantee a great kickoff meeting planning session?</p>
    <h4>Limit the Number of Attendants</h4>
    <p>Early in my career, I was working on a project for the board of education for a county near my hometown. We had just won the job and I was told the client’s team was coming into the office to meet with our staff.</p>
    <p>When it was time for the meeting, ten people attended. That translated to ten opinions, ten people interrupting one another, ten potential bathroom breaks — ten cooks in the kitchen spoiling the broth.</p>
    <p>It was a nightmare and we accomplished nothing but frustrating our brand new client.</p>
    <p>When scheduling your first meeting, be sure to indicate that only the decision maker needs to attend. And if ten people make the decision, put your boots on and start walking because you should have never accepted the project under those terms.</p>
    <p>I would suggest one or two people max come to your kickoff meeting. You will get more done, have less interruption, and have one or two people accountable for deliverables you will be requesting. Guess what? The finger pointing just got reduced as well.</p>
    <h4>State the Intended Results and Outcome</h4>
    <p>Open your meeting with what you’ll be going over, and what the client will be walking away with.</p>
    <p>Setting expectations is something you should try to do every time you meet with a client to maintain efficiency and to show that you take their time seriously.</p>
    <p>Most importantly, they will understand why they are meeting and be in the right mental state for your chat.</p>
    <h3>The Kickoff Meeting</h3>
    <p>Here is my meeting structure for kickoff meetings.</p>
    <p>As you work through the meeting structure, you should be assigning responsibilities to your client and to your team.</p>
    <p>After each task assignment, you should be asking the person being assigned the task, "When can you have that by?"</p>
    <p>What I typically do is have a calendar nearby and I give them a little more time than they suggest. Typically, the client is eager to please and is sometimes unrealistic. Give them a little more time if you can spare it.</p>
    <p>I do <em>gently</em> remind clients that if their deliverable is late, all dates are pushed back and we typically will charge extra unless given 15 days notice. It’s harsh, but it keeps people accountable and, in the end, makes them a happier customer because their project is on time.</p>
    <p>In general, a good kickoff meeting can be accomplished in <strong>2  hours.</strong></p>
    <p><img src="http://cdn.sixrevisions.com/0348-14_web_development_kickoff_meeting_2hours.png" width="550" height="596" style="max-width: 100%; height: auto;"></p>
    <h4>Scope and Goal Review</h4>
    <p>I like to start my kickoff meeting like a thesis statement in a scientific paper: I state the primary goal of the project and provide a brief summary.</p>
    <p>The <a href="http://en.wikipedia.org/wiki/SMART_criteria#Terms_behind_the_letters" title="SMART criteria - wikipedia.org" rel="nofollow external" class="bo">SMARTer the primary goal</a>, the better. For example, depending on the scale of the project, it might even be as specific as: "The goal of the project is to drive traffic to the site’s <a href="http://sixrevisions.com/user-interface/10-tips-for-optimizing-web-form-submission-usability/" title="10 Tips for Optimizing Web Form Submission Usability" rel="nofollow external" class="bo">contact form</a> and have users fill it out."</p>
    <p>Then I review the scope of work that has been signed by the client. This allows you to set the stage and confirm what it is you are building, while refreshing everyone on what the project is all about.</p>
    <h4>Mechanical</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-05_web_development_kickoff_meeting_mechanicaldetails.jpg" width="550" height="908" style="max-width: 100%; height: auto;"></p>
    <p>Get the server, email, and analytics information out of the way early. You don’t want to be two weeks away <a href="http://sixrevisions.com/web-development/10-simple-tips-for-launching-a-website/" title="10 Simple Tips for Launching a Website" rel="nofollow external" class="bo">from launch</a> and have to set up a server.</p>
    <h4>Technical</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-06_web_development_kickoff_meeting_technicaldetails.jpg" width="550" height="520" style="max-width: 100%; height: auto;"></p>
    <p>Your technical discussion will absolutely take the most of the time.</p>
    <p>This portion defines the project and you may need more than just the half sheet of space so have some scrap paper ready.</p>
    <p>What you ultimately want to walk away with are three important pieces of information that everyone should agree on:</p>
    <ul>
    <li>What are the primary and secondary goals of the project?</li>
    <li>What do we want people to do?</li>
    <li>What features will the project have to support these goals?</li>
    </ul>
    <h4>Copy and Media</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-07_web_development_kickoff_meeting_copymediadetails.jpg" width="550" height="712" style="max-width: 100%; height: auto;"></p>
    <p>Content, imagery, and rich media (like videos) is a subject neglected in a lot in planning meetings, but it’s one of the most expensive and time-consuming things to produce so it should be covered as soon as possible.</p>
    <p>For example, most companies that I work with that produce video don’t do it quickly or cheaply. Get the ball rolling early on any video production needed, as well as reinforce who is purchasing any needed stock photography (<a href="http://sixrevisions.com/project-management/tips-freelancer-design-contracts/" title="Tips for Your Freelance Design Contracts" rel="nofollow external" class="bo">it was in your contract right?</a>).</p>
    <h4>Aesthetic</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-08_web_development_kickoff_meeting_aestheticdetails.jpg" width="550" height="712" style="max-width: 100%; height: auto;"></p>
    <p>The look and feel of a site is tough to nail down.</p>
    <p>Early in my career, the conversation usually went something like this: "How did you envision your site looking?" That question would be followed by the client mentioning five of their competitors’ websites — all which would typically looked horrible.</p>
    <p>You are the professional. You know what looks good and what doesn’t.</p>
    <p>Instead of having them start and govern the conversation about the look-and-feel of the website project, ask them a few questions about how they want their site to <em>feel</em> and the general style. They hired you to figure out the rest.</p>
    <h4>Release</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-09_web_development_kickoff_meeting_release.jpg" width="550" height="712" style="max-width: 100%; height: auto;"></p>
    <p>When and how a site will launch seems like an obvious thing you will want to establish as soon as possible. The "when" is usually covered by the contract, but the "how" is sometimes forgotten.</p>
    <p>Will there be a beta testing period prior to launch? How about slowly rolling it out to gain interest and test the load on our servers? These are some things to cover in the kickoff meeting.</p>
    <h4>Support and Revisions</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-10_web_development_kickoff_meeting_supportrevisions.png" width="550" height="712" style="max-width: 100%; height: auto;"></p>
    <p>This is a great discussion that can potentially generate recurring revenue for your company.</p>
    <p>How do they plan on updating the site after it has launched? What if the web server crashes? What about additional features? What happens if a great idea comes up in the middle of the project that requires augmenting the original scope of work — how do we deal with that?</p>
    <h4>Marketing</h4>
    <p><img src="http://cdn.sixrevisions.com/0348-11_web_development_kickoff_meeting_marketing.png" width="550" height="712" style="max-width: 100%; height: auto;"></p>
    <p>What type of marketing materials need to be prepared for this project? Do social media accounts need to be set up? What about traditional marketing methods? Do any parts of the marketing campaign need assets from our creative department? When and how should these efforts go live? </p>
    <h4>Review</h4>
    <p>By this time, your customer (and you) are probably exhausted, but it’s a good exercise to quickly run through the deliverables, due dates, and a summary of the key points discussed in the kickoff meeting.</p>
    <h3>After the Kickoff Meeting</h3>
    <p>After the client has left, what I typically do is I will punch in the due dates into our project management software (we use <a href="https://www.activecollab.com/" rel="nofollow external" class="bo">activeCollab</a>).</p>
    <p><img src="http://cdn.sixrevisions.com/0348-02_web_development_kickoff_meeting_activecollab.jpg" width="550" height="383" style="max-width: 100%; height: auto;"></p>
    <p>Then I’ll run a quick report. I’ll send the report to the client via email as a reminder of the things we’ve discussed, along with a note thanking them for the time they have invested into the kickoff meeting.</p>
    <h3>Related Content</h3>
    <ul>
    <li><a href="http://sixrevisions.com/project-management/website-architecture/" rel="nofollow external" class="bo">The Secret to Building Large Websites: Website Architecture</a></li>
    <li><a href="http://sixrevisions.com/web-development/crazy-tips-help-become-better-coder/" rel="nofollow external" class="bo">7 Crazy Tips That Will Help You Become a Better Coder</a></li>
    <li><a href="http://sixrevisions.com/web-development/planning-your-e-commerce-website/" rel="nofollow external" class="bo">Planning your E-Commerce Website</a></li>
    <li>
    <em>Related categories</em>: <a href="http://sixrevisions.com/category/project-management/" rel="nofollow external" class="bo">Project Management</a> and <a href="http://sixrevisions.com/category/web-development/" rel="nofollow external" class="bo">Web Development</a>
    </li>
    </ul>
    <h3>About the Author</h3>
    <p><img src="http://cdn.sixrevisions.com/authors/gary_williams_small.jpg" alt="" width="80" height="80" style="max-width: 100%; height: auto;"><span><strong>Gary Williams</strong> is the co-founder and CEO of the web development agency <a href="http://lbm.co/" rel="nofollow external" class="bo">LogicBomb Media</a> (Twitter: <a href="https://twitter.com/lbm_co" rel="nofollow external" class="bo">@lmb_co</a>) near Atlanta, Georgia. He and his team specialize in data-heavy Web and mobile applications for companies like Nintendo, ESPN, and Travel Channel. Follow him on Twitter <a href="https://twitter.com/dolbex" rel="nofollow external" class="bo">@dolbex</a>.</span></p>
    <p>The post <a href="http://sixrevisions.com/project-management/web-development-kickoff-meeting/" rel="nofollow external" class="bo">How to Get Your Web Development Projects Off to a Good Start</a> appeared first on <a href="http://sixrevisions.com" rel="nofollow external" class="bo">Six Revisions</a>.</p>
    </div>
]]>
</Body>
<Summary>If you’re anything like my team, you probably want to dive right in head first into a web development project as soon as you possibly can. Because we love our jobs — we’re all very passionate...</Summary>
<Website>http://feedproxy.google.com/~r/SixRevisions/~3/TQEgsh79AoI/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31315/guest@my.umbc.edu/61e4e7a3a4774365599644a81eb49089/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>database</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>project-management</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 14 Jun 2013 06:00:04 -0400</PostedAt>
<EditAt>Fri, 14 Jun 2013 06:00:04 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="31317" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31317">
<Title>Get off to a fast start with jQuery</Title>
<Body>
<![CDATA[
    <div class="html-content">In this introduction, you’ll learn what jQuery is, how to include it in your applications, and how jQuery, jQuery UI, and plugins can simplify JavaScript development<div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fget-fast-start-jquery&amp;t=Get+off+to+a+fast+start+with+jQuery" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fget-fast-start-jquery&amp;t=Get+off+to+a+fast+start+with+jQuery" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fget-fast-start-jquery&amp;t=Get+off+to+a+fast+start+with+jQuery" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fget-fast-start-jquery&amp;t=Get+off+to+a+fast+start+with+jQuery" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fget-fast-start-jquery&amp;t=Get+off+to+a+fast+start+with+jQuery" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/165665169372/u/49/f/502346/c/32632/s/2d481d14/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/165665169372/u/49/f/502346/c/32632/s/2d481d14/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>In this introduction, you’ll learn what jQuery is, how to include it in your applications, and how jQuery, jQuery UI, and plugins can simplify JavaScript development     </Summary>
<Website>http://feedproxy.google.com/~r/net/topstories/~3/UZxvNj3hwk0/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31317/guest@my.umbc.edu/1babb382f6f32c6a14bc07182d228742/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>net</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 14 Jun 2013 06:00:00 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="31313" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31313">
<Title>What Leap Motion And Google Glass Mean For Future User Experience</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <table width="650">
    <tbody>
    <tr>
    <td>
    <div>
    <img src="http://statisches.auslieferung.commindo-media-ressourcen.de/advertisement.gif" alt="" style="max-width: 100%; height: auto;"><br><a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=1" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=1" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=2" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=2" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=3" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=3" alt="" style="max-width: 100%; height: auto;"></a>
    </div>
    </td>
    </tr>
    </tbody>
    </table>
    <p>With the Leap Motion controller being released on June 27th and the Google Glass Explorer program already live, it is obvious that our reliance on the mouse or even the monitor to interact with the Web will eventually become obsolete.</p>
    <p>The above statement seems like a given, considering that technology moves at such a rapid pace. Yet in 40 years of personal computing, our methods of controlling our machines haven’t evolved beyond using a mouse, keyboard and perhaps a stylus. Only in the last six years have we seen mainstream adoption of touchscreens.</p>
    <p>Given that emerging control devices such as the Leap Controller are enabling us to interact with near pixel-perfect accuracy in 3-D space, our computers will be less like dynamic pages of a magazine and more like windows to another world. To make sure we’re on the same page, please take a minute to check out what the <a href="http://www.youtube.com/embed/_d6KuiuteIA" rel="nofollow external" class="bo">Leap Motion controller</a> can do:</p>
    <p></p>
    <div class="embed-container"><iframe src="http://www.youtube.com/embed/_d6KuiuteIA" frameborder="0" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowFullScreen">[Video]</iframe></div>
    <br>
    <em>“<a href="http://www.youtube.com/embed/_d6KuiuteIA" rel="nofollow external" class="bo">Introducing the Leap Motion</a>”</em>
    <p>Thanks to monitors becoming portable with Google Glass (and the competitors that are sure to follow), it’s easy to see that the virtual world will no longer be bound to flat two-dimensional surfaces.</p>
    <p>In this article, we’ll travel five to ten years into the future and explore a world where Google Glass, Leap Motion and a few other technologies are as much a part of our daily lives as our smartphones and desktops are now. We’ll be discussing a new paradigm of human-computer interface. <strong>The goal of this piece is to start a discussion with forward-thinking user experience designers</strong>, and to explore what’s possible when the mainstream starts to interact with computers in 3-D space.</p>
    <blockquote><p><strong>Please note</strong>: We’re exploring an entirely hypothetical scenario, and these are opinions, some of which you may not agree with. However, the opinions are based on current trends, statistics and existing technology. If you’re the kind of designer who is interested in developing the future, I encourage you to read the sources that are linked throughout the article.</p></blockquote>
    <h3>Setting The Stage: A Few Things To Consider</h3>
    <p>Prior to the introduction of the iPhone in 2007, many considered the smartphone to be for techies and business folk. But in 2013, you’d be hard pressed to find someone in the developed world who isn’t checking their email or tweeting at random times.</p>
    <p>So, it’s understandable to think that a conversation about motion control, 3-D interaction and portable monitors is premature. But if the mobile revolution has taught us anything, it’s that people crave connection without being tethered to a stationary device.</p>
    <p>To really understand how user experience (UX) will change, we first have to consider the possibility that social and utilitarian UX will be taking place in different environments. In the future, people will use the desktop primarily for utilitarian purposes, while “social” UX will happen on a virtual layer, overlaying the real world (thanks to Glass). Early indicators of this are that <a href="http://thenextweb.com/facebook/2012/10/24/facebook-anticipates-growth-happening-in-mobile-usage-rather-than-through-personal-computers/" rel="nofollow external" class="bo">Facebook anticipates its mobile growth to outpace its PC growth</a> and that nearly <a href="http://www.go-gulf.com/blog/smartphone/" rel="nofollow external" class="bo">one-seventh of the world’s population own smartphones</a>.</p>
    <p>The only barrier right now is that we lack the technology to truly merge the real and virtual worlds. But I’m getting ahead of myself. Let’s start with something more familiar.</p>
    <h3>The Desktop</h3>
    <p>Right now, UX on the desktop cannot be truly immersive. Every interaction requires physically dragging a hunk of plastic across a flat surface, which approximates a position on screen. While this is accepted as commonplace, it’s quite unnatural. The desktop is the only environment where you interact with one pixel at a time.</p>
    <p>Sure, you could create the illusion of three dimensions with drop shadows and parallax effects, but that doesn’t change the fact that the user may interact with only one portion of the screen at a time.</p>
    <p>This is why <strong>the Leap Motion controller is revolutionary</strong>. It allows you to interact with the virtual environment using all 10 fingers and real-world tools in 3-D space. It is as important to computing as analog sticks were to video games.</p>
    <h3>The Shift In The Way We Interact With Machines</h3>
    <p>To wrap our heads around just how game-changing this will be, let’s go back to basics. One basic UX and artificial intelligence test for any new platform is a simple game of chess.</p>
    <p><a href="http://commons.wikimedia.org/wiki/File:Agat-7_Chess.png" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/06/Virtual-Chess-e1370636058728.png" alt="Virtual Chess" width="500" height="375" style="max-width: 100%; height: auto;"></a><br>
    <em>(Image: <a href="http://commons.wikimedia.org/wiki/File:Agat-7_Chess.png" rel="nofollow external" class="bo">Wikimedia Commons</a>)</em></p>
    <p>In the game of chess below, thanks to motion controllers and webcams, you’ll be able to “reach in” and grab a piece, as you watch your friend stress over which move to make next.</p>
    <p><a href="http://algerblog.blogspot.com/2011/12/quality-time.html" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/06/Real-Chess-e1370636247876.jpg" alt="Now you can watch your opponent sweat." width="500" height="375" style="max-width: 100%; height: auto;"></a><br>
    <em>Now you can watch your opponent sweat. (Image: <a href="http://algerblog.blogspot.com/2011/12/quality-time.HTML" rel="nofollow external" class="bo">Algernon D’Ammassa</a>)</em></p>
    <p>In a game of The Sims, you’ll be able to rearrange furniture by moving it with your hands. CAD designers will use their hands to “physically” manipulate components (and then send their design to the <a href="http://www.staples.com/3-D-Printing/cat_CL205651?icid=SearchResults3-D" rel="nofollow external" class="bo">3-D printer they bought from Staples</a> for prototyping.)</p>
    <p>While the lack of tactile feedback might deter mainstream adoption early on, <a href="http://www.disneyresearch.com/project/surround-haptics-immersive-tactile-experiences/" rel="nofollow external" class="bo">research into haptics</a> is already enabling developers to simulate physical feedback in the real world to correspond with the actions of a user’s virtual counterpart. Keep this in mind as you continue reading.</p>
    <p>Over time, this level of 3-D interactivity will fundamentally change the way we use our desktops and laptops altogether.</p>
    <p><strong>Think about it</strong>: The desktop is a perfect, quiet, isolated place to do more involved work like writing, photo editing or “hands-on” training to learn something new. However, a 3-D experience like those mentioned above doesn’t make sense for social interactions such as on Facebook or even reading the news, which are <a href="http://www.businessesgrow.com/2013/03/27/what-a-blog-post-will-look-like-in-2020/" rel="nofollow external" class="bo">more becoming of mobile</a>.</p>
    <p>With immersive, interactive experiences being available primarily via the desktop, it’s hard to imagine users wanting these two experiences to share the same screen.</p>
    <p>So, what would a typical desktop experience look like?</p>
    <h3>Imagine A Cooking Website For People Who Can’t Cook</h3>
    <p>With this cooking website for people who can’t cook, we’re not just talking about video tutorials or recipes with unsympathetic instructions, but rather immersive simulations in which an instructor leads you through making a virtual meal from prep to presentation.</p>
    <p>Interactions in this environment would be so natural that the real design challenge is to put the user in a kitchen that’s believable as their own.</p>
    <p>You wouldn’t click and drag the icon that represents sugar; you would reach out with your virtual five-fingered hand and grab the life-sized “box” of Domino-branded sugar. You wouldn’t click to grease the pan; you’d mimic pushing the aerosol nozzle of a bottle of Pam.</p>
    <p>The Tokyo Institute of Technology has already built such a simulation in the real world. So, transferring the experience to the desktop is only a matter of time.</p>
    <p></p>
    <div class="embed-container"><iframe src="http://www.youtube.com/embed/F565MHCfsSo" frameborder="0" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowFullScreen">[Video]</iframe></div>
    <br>
    <em>“<a href="http://www.youtube.com/embed/F565MHCfsSo" rel="nofollow external" class="bo">Cooking simulator will help you cook a perfect steak every time</a>”</em>
    <p><strong>UX on the future desktop</strong> will be about simulating physics and creating realistic environments, as well as tracking head, body and <a href="https://www.youeye.com/how-it-works" rel="nofollow external" class="bo">eyes</a> to create intuitive 3-D interfaces, based on HTML5 and <a href="http://www.awwwards.com/22-experimental-webgl-demo-examples.HTML" rel="nofollow external" class="bo">WebGL</a>.</p>
    <p>Aside from the obvious hands-on applications, such as CAD and art programs, the technology will shift the paradigm of UX and user interface (UI) design in ways that are currently difficult to fathom.</p>
    <p>The problem right now is that we currently lack a set of clearly defined 3-D gestures to interact with a 3-D UI. Designing UIs will be hard without knowing what our bodies will have to do to interact.</p>
    <p>The closest we have right now to defined gestures are those created by <a href="http://www.youtube.com/results?search_query=kinect+ui+hacks&amp;oq=kinect+ui+hacks&amp;gs_l=youtube.3...903891.906571.0.906817.15.15.0.0.0.0.134.938.14j1.15.0...0.0...1ac.1.hF5nT0Br_Ik" rel="nofollow external" class="bo">Kinect hackers</a> and John Underkoffler of <a href="http://www.oblong.com/g-speak/" rel="nofollow external" class="bo">Oblong Technology</a> (the team behind Minority Report’s UI).</p>
    <p>In his TED talk from 2010, Underkoffler demonstrates probably the most advanced example of 3-D computer interaction that you’re going to see for a while. If you’ve got 15 minutes to spare, I highly recommend watching it:</p>
    <p></p>
    <div class="embed-container"><iframe src="http://www.youtube.com/embed/b6YTQJVzwlI" frameborder="0" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowFullScreen">[Video]</iframe></div>
    <br>
    <em>John Underkoffler’s talk “<a href="http://www.youtube.com/embed/b6YTQJVzwlI" rel="nofollow external" class="bo">Pointing to the Future of UI</a>”</em>
    <p>Now, before you start arguing, “Minority Report isn’t practical — humans aren’t designed for that!” consider two things:</p>
    <ol>
    <li>We won’t likely be interacting with 60-inch room-wrapping screens the way Tom Cruise does in Minority Report; therefore, our gestures won’t need to be nearly as big.</li>
    <li>The human body rapidly adapts to its environment. Between the years 2000 and 2010, a period when home computers really went mainstream, <a href="http://www.health.state.mn.us/divs/hpcd/cdee/occhealth/indicators/carpal-tunnel.HTML" rel="nofollow external" class="bo">reports of Carpal Tunnel Syndrome dropped by nearly 8%</a>.</li>
    </ol>
    <p><a href="http://www.health.state.mn.us/divs/hpcd/cdee/occhealth/indicators/carpal-tunnel.html" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/06/Graph-of-Carpel-Tunnel.png" alt="Graph of Carpel Tunnel" width="452" height="230" style="max-width: 100%; height: auto;"></a><br>
    <em>(Image: <a href="http://www.health.state.mn.us/divs/hpcd/cdee/occhealth/indicators/carpal-tunnel.html" rel="nofollow external" class="bo">Minnesota Department of Health</a>)</em></p>
    <p>However, because the Leap Motion controller is less than $80 and will be available at Best Buy, this technology isn’t just hypothetical, sitting in a lab somewhere, with a bunch of geeks saying “Wouldn’t it be cool if…”</p>
    <p>It’s real and it’s cheap, which really means we’re about to enter the Wild West of true 3-D design.</p>
    <h3>Social Gets Back To The Real World</h3>
    <p>So, where does that leave social UX? Enter Glass.</p>
    <p>It’s easy to think that head-mounted augmented reality (AR) displays, such as Google Glass, will not be adopted by the public, and in 2013 that might be true.</p>
    <p>But remember that we resisted the telephone when it came out, for <a href="http://news.cnet.com/8301-1023_3-57573966-93/google-glass-and-the-third-half-of-your-brain/" rel="nofollow external" class="bo">many of the same privacy concerns</a>. The <a href="http://www.maebrussell.com/Articles%20and%20Notes/Do%20cell%20phones%20cook%20cells.HTML" rel="nofollow external" class="bo">same goes for mobile phones</a> and <a href="http://www.computerworld.com/s/article/9014118/Ten_dangerous_claims_about_smart_phone_security" rel="nofollow external" class="bo">for smartphones</a> around 2007.</p>
    <p>So, while first-generation Glass won’t likely be met with widespread adoption, it’s the introduction of a new phase. ABI Research predicts that the wearable device market will <a href="http://www.abiresearch.com/press/wearable-computing-devices-like-apples-iwatch-will" rel="nofollow external" class="bo">exceed 485 million annual shipments by 2018.</a></p>
    <p>According to Steve Lee, Glass’ product director, the goal is to “allow people to have more human interactions” and to “get technology out of the way.”</p>
    <p>First-generation Glass performs Google searches, tells time, gives turn-by-turn directions, reports the weather, snaps pictures, records video and does Hangouts — which are many of the reasons why our phones are in front of our faces now.</p>
    <p>Moving these interactions to a heads-up display, while moving important and more heavy-duty social interactions to a wrist-mounted display, like the <a href="http://getpebble.com/" rel="nofollow external" class="bo">Pebble smartwatch</a>, eliminates the phone entirely and enables you to truly see what’s in front of you.</p>
    <p><a href="http://getpebble.com" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/06/pebble_smartwatch_dm_120418_wblog-e1370636774109.jpg" alt="pebble_smartwatch_dm_120418_wblog" width="500" height="281" style="max-width: 100%; height: auto;"></a><br>
    <em>(Image: <a href="http://getpebble.com/" rel="nofollow external" class="bo">Pebble</a>)</em></p>
    <p>Now, consider the possibility that something like the Leap Motion controller could become small enough to integrate into a wrist-mounted smartwatch. This, combined with a head-mounted display, would essentially give us the ability to create an interactive virtual layer that overlays the real world.</p>
    <p>Add <a href="http://www.popsci.com/technology/article/2012-09/haptic-armband-improves-muscle-memory-helping-blind-athletes-train-better" rel="nofollow external" class="bo">haptic wristband</a> technology and a Bluetooth connection to the smartwatch, and you’ll be able to <a href="http://www.popsci.com/technology/article/2010-07/fingertip-mounted-haptic-interface-lets-you-feel-virtual-3-d-objects" rel="nofollow external" class="bo">“feel” virtual objects</a> as you physically manipulate them in both the real world and on the desktop. While this might still sound like science fiction, with Glass reportedly to be priced between $299 and $499 and Leap Motion at $80 and Pebble being $150, widespread affordability of these technologies isn’t entirely impossible.</p>
    <h3>Social UX In The Future: A Use Case</h3>
    <p>Picture yourself walking out of the mall, and your close friend Jon updates his status. A red icon appears in the top right of your field of vision. Your watch displays Jon’s avatar, which says, “Sooo hungry right now.”</p>
    <p>You say, “OK, Glass. Update status: How about lunch? What do you want?” and keep walking.</p>
    <p>“Tacos.”</p>
    <p>You say, “OK, Glass. Where can I get good Mexican food?” 40 friends have favorably rated <a href="http://facebook.com/rosascafe" rel="nofollow external" class="bo">Rosa’s Cafe</a>. Would you like directions? “Yes.” The navigation starts, and you’re en route.</p>
    <p>You reach the cafe, but Jon is 10 minutes away. Would you like an audiobook while you wait? “No, play music.” A smart playlist compiles exactly 10 minutes of music that perfectly fits your mood.</p>
    <p>“OK, Glass. Play Angry Birds 4.”</p>
    <p>Across the table, 3-D versions of the little green piggies and their towers materialize.</p>
    <p>In front of you are a red bird, a yellow bird, two blue birds and a slingshot. The red bird jumps up, you pull back on the slingshot, the trajectory beam shows you a path across the table, you let go and knock down a row of bad piggies.</p>
    <p>Suddenly, an idea comes to you. “OK, Glass. Switch to Evernote.”</p>
    <p>A piece of paper and a pen are projected onto the table in front of you, and a bulletin board appears to the left.</p>
    <p>You pick up the AR pen, jot down your note, move the paper to the appropriate bulletin, and return to Angry Birds.</p>
    <p>You could make your game visible to other Glass wearers. That way, others could play with you — or, at the very least, would know you’re not some crazy person pretending to do… whatever you’re doing across the table.</p>
    <p>When Jon arrives, notifications are disabled. You push the menu icon on the table and select your meal. Your meal arrives; you take photos of your food; eat; publish to Instagram 7.</p>
    <p>Before you leave, the restaurant gives a polite notification, letting you know that a coupon for 10% off will be sent to your phone if you write a review.</p>
    <h3>How Wearable Technology Interacts With Desktops</h3>
    <p>Later, having finished the cooking tutorial on the desktop, you decide it’s time to make the meal for real. You put on Glass and go to the store. The headset guides you directly to the brands that were advertised “in game.” After picking out your ingredients, you receive a notification that a manufacturer’s coupon has been sent to your phone and can be used at the check-out.</p>
    <p>When you get home, you lay a carrot on the cutting board and an overlay projects guidelines on where to cut. You lay out the meat, and a POW graphic is overlaid, <strong>showing you where to hit for optimal tenderness</strong>:</p>
    <p><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/06/augmented-meat-300x225.png" alt="Augmented Meat" width="500" height="375" style="max-width: 100%; height: auto;"><br>
    <em>Image source?</em></p>
    <p>You put the meat in the oven; Glass starts the timer. You put the veggies in the pan; Glass overlays a pattern to show where and when to stir.</p>
    <p>While you were at the store, Glass helped you to pick out the perfect bottle of wine to pair with your meal (based on reviews, of course). So, you pour yourself a glass and relax while you wait for the timer to go off.</p>
    <p>In the future, augmented real-world UX experiences will be turned into real business. The more you enhance real life, the more successful your business will be. After all, is it really difficult to imagine this cooking experience being turned into a game?</p>
    <h3>What Can We Do About This Today?</h3>
    <p>If you’re the kind of UI designer who seeks to push boundaries, then the best thing you can do right now is think. Because the technology isn’t 100% available, the best you can do is open your imagination to what will be possible when the average person has evolved beyond the keyboard and mouse.</p>
    <p>Draw inspiration from websites and software that simulate depth to create dynamic, layered experiences that can be easily operated without a mouse. The website of agency <a href="http://blacknegative.com/" rel="nofollow external" class="bo">Black Negative</a> is a good example of future-inspired “flat” interaction. It’s easy to imagine interacting with this website without needing a mouse. The new <a href="http://new.myspace.com" rel="nofollow external" class="bo">Myspace</a> is another.</p>
    <p>To go really deep, look at the different <a href="http://www.chromeexperiments.com/" rel="nofollow external" class="bo">Chrome Experiments</a>, and find a skilled HTML5 and WebGL developer to discuss what’s in store for the future. The software and interactions that come from your mind will determine whether these technologies will be useful.</p>
    <h3>Conclusion</h3>
    <p>While everything I’ve talked about here is conceptual, I’m curious to hear what you think about how (or even if) these devices will affect UIs. I’d also love to hear your vision of future UIs.</p>
    <p>To get started, let me ask you two questions:</p>
    <ol>
    <li>How will the ability to reach into the screen and interact with the virtual world shape our expectations of computing?</li>
    <li>How will untethering content from flat surfaces fundamentally change the medium?</li>
    </ol>
    <p>I look forward to your feedback. Please share this article if you’ve enjoyed this trip into the future.</p>
    <p><em>(il) (al)</em></p>
    <hr>
    <p><small>© Tommy Walker for <a href="http://www.smashingmagazine.com" rel="nofollow external" class="bo">Smashing Magazine</a>, 2013.</small></p>
    </div>
]]>
</Body>
<Summary>        With the Leap Motion controller being released on June 27th and the Google Glass Explorer program already live, it is obvious that our reliance on the mouse or even the monitor to interact...</Summary>
<Website>http://www.smashingmagazine.com/2013/06/14/what-leap-motion-and-google-glass-mean-for-future-user-experience/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31313/guest@my.umbc.edu/9456d3548896db11e0aec9e5c76df6f6/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>ux-design</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 14 Jun 2013 05:42:31 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="31314" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31314">
<Title>30 fresh WordPress business themes</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/thumbnail29.jpg" alt="Thumbnail" width="200" height="160" style="max-width: 100%; height: auto;">Most of the time, the first contact a customer will have with your business is through your website. Consequently, the website could make or break your business. To ensure that the website makes it, having it be both aesthetically pleasing and user friendly is imperative.</p> <p>Look for five main features in a corporate WordPress theme before purchasing it: responsive design, colorization capabilities, browser compatibility, an advanced options panel, and support.</p> <p>First, a responsive design will allow your users to view the website from any device (smartphone, tablet, laptop, etc). Colorization capabilities free you to select any colors you like for the website. This is important because you want to match your brand’s colors. Hence, choose only a WordPress theme that offers unlimited colors. The theme should be supported by most internet browsers, including Firefox, internet Explorer, Safari, Opera and Chrome. Nowadays, many theme developers sell their themes with an advanced options panel, which enables you to set a myriad of preferences without the hassle of learning code. Don’t go for a theme that doesn’t offer support into the future, including periodic updates and email support.</p> <p>Now that that’s said, I have compiled a list of 30 splendid corporate WordPress themes to help web designers and businesses make informed decisions when developing or buying a corporate theme.</p> <p> </p> <h1>PAX </h1> <p><a href="http://wpadaptive.com/pax/preview/" rel="nofollow external" class="bo">Pax</a> is a corporate WordPress theme supported by all devices and tested on iPad, iPhone and Android 2.3+. Over and above being responsive, Pax has unlimited colorization capabilities. This theme looks incredible on most internet browsers, including internet Explorer 10+, Safari, Chrome and Firefox. Created by Adaptive Themes, Pax also packs a punch in its other features. It comes with a ton of shortcodes, a free Uslider plugin (which would normally cost you about $30), layered PSD files and an options panel. From the panel, you can set many options since the theme is highly customizable. Lastly, you get two layout styles, boxed and wide.</p> <p><a href="http://wpadaptive.com/pax/preview/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/1-Pax.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Customize </h1> <p><a href="http://kopatheme.com/demo/customize-responsive-wordpress-theme/" rel="nofollow external" class="bo">Customize</a> is a fully responsive WordPress theme. This incredibly attractive theme supports modern browsers, old browsers (IE 7+), touch devices and responsive designs. Other browsers supported by this theme are Firefox, Chrome, Opera and Safari. Technical support is also prompt. The sales page claims that your queries will be answered within 24 hours of logging them. Created by Kopasoft, Customize also has integrated social media, which enables a business to connect with and satisfy its customers promptly. Additionally, it comes with an easy drag-and-drop layout manager, a visual shortcode generator and multiple sliders. It makes for a great corporate theme, especially for tech businesses.</p> <p><a href="http://kopatheme.com/demo/customize-responsive-wordpress-theme/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/2-Customize.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Super Spark</h1> <p><a href="http://themes.goodlayers.com/?theme=superspark" rel="nofollow external" class="bo">Super Spark</a> is an awesomely constructed theme. It is responsive, it supports unlimited colors, most browsers support it, and its creator has gone to great lengths to assist users with their queries about it. Created by Good Layers, the theme also features a live color changer, multiple footer layouts, multiple blog styles, a built-in translator, and a font and logo uploader. Additionally, the theme has a custom pricing table, which sets it apart from other business themes. It was created with the creative industry in mind.</p> <p> <a href="http://themes.goodlayers.com/?theme=superspark" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/3-Super-Spark.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Grander </h1> <p><a href="http://grander.adrianholobut.com/wp/" rel="nofollow external" class="bo">Grander</a> is a beautiful multipurpose WordPress theme that could be used to make a breathtaking corporate website. It is responsive and comes with multiple color schemes, 25 to be exact. Its advanced admin panel is also to die for, allowing you to change settings for pricing, typography, meta data, contact information and social media. Created by Holobest, it also features a minimal design, a shortcode generator, multiple custom post types, page templates for members and services, Google Maps support, pagination capabilities, and custom widgets (including for Twitter and video). The theme is compatible with most browsers.</p> <p> <a href="http://grander.adrianholobut.com/wp/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/4-Grander1.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Proma</h1> <p><a href="http://teothemes.com/wp/proma" rel="nofollow external" class="bo">Proma</a> is an incredible WordPress 3.5+ theme. It is responsive, easy to customize, and compatible with major browsers. It supports unlimited colors and, get this, unlimited fonts, and it has an options panel where you can easily set preferences. Created by Final Destiny, Proma also comes with a “revolution” slider, a “flex” slider, custom widgets, a custom color scheme, multiple page templates, custom post types, and a unique filterable portfolio. You also get appropriate documentation, and the creator will do his best to address your concerns.</p> <p><a href="http://teothemes.com/wp/proma" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/5-Proma.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>FreshBiz</h1> <p><a href="http://www.mnkystudio.com/theme-9" rel="nofollow external" class="bo">FreshBiz</a> is a cool multipurpose theme that can be used for any type of corporate website. It comes with unlimited color and styles and is compatible with internet Explorer 8+, Chrome, Firefox and Safari. Created by MNKY, this theme has an intelligent options panel, where you can set the logo, header, menu, title area, footer, typography, blog area and much more. And it is responsive.</p> <p><a href="http://www.mnkystudio.com/theme-9" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/6-FreshBiz.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>FreshLook</h1> <p><a href="http://designarethemes.com/theme/?theme=freshlook" rel="nofollow external" class="bo">Freshlook</a> is, well, a breath of fresh air. This responsive theme is highly customizable, with a rich feature set, including a visual shortcode editor, over 300 Google Web Fonts, unlimited sidebars and more. In addition, the theme supports unlimited color skins, which could generate profit for the creator. Created by Designare, Freshlook is supported by major browsers and has a powerful settings panel where you can build custom skins and change all of the main styles. You also get to choose from custom patterns and colors for every section of a page.</p> <p><a href="http://designarethemes.com/theme/?theme=freshlook" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/7-Freshlook.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Nebraska</h1> <p><a href="http://themeforest.unitedthemes.com/?theme=nebraskawp" rel="nofollow external" class="bo">Nebraska</a> is a fully translation-ready corporate theme. It comes with many features. From the advanced options panel, you can set custom codes and sidebar options. You also get a page creator to help you create a unique corporate theme. Created by United Themes, Nebraska offers unlimited accent colors and compatibility with internet Explorer 10+, Firefox, Chrome and more. The custom widgets (including for posts, Twitter, Flickr and social icons) enable businesses to reduce their workload while streamlining their processes.</p> <p><a href="http://themeforest.unitedthemes.com/?theme=nebraskawp" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/8-Nebraska.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Inovado</h1> <p><a href="http://inovado.mintithemes.com/" rel="nofollow external" class="bo">Inovado</a> is aesthetically pleasing, to say the least. And this is complemented by a myriad of features. The theme is responsive and Retina-ready, meaning that your images will not lose their sharpness and clarity, whatever the device. It also comes with an impressive 500+ Google Web Fonts and unlimited colors. Created by Minti, it is compatible with internet Explorer 8 and 9, Firefox, Safari and Chrome. It also has sharp graphics, localization functionality, a built-in SEO base, premium sliders, and child-theme compatibility. It works with WordPress 3.5+.</p> <p><a href="http://inovado.mintithemes.com/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/9-Inovado.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Nautica </h1> <p><a href="http://nautica.beopenthemes.com/" rel="nofollow external" class="bo">Nautica</a> is an HTML5-, CSS3- and widget-ready theme, compatible with WordPress 3.4+ and major browsers. Judging by its ratings and comments, Nautica has a lot to offer businesses. Created by BeOpen, the theme pays great attention to detail. The responsive multi-platform theme allows you to customize almost all aspects, including the logo, slider, menu, call to action, services, portfolio, tabs, processes and testimonials.</p> <p><a href="http://nautica.beopenthemes.com/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/10-Nautica.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Eudora</h1> <p><a href="http://eudora.designprefix.com/" rel="nofollow external" class="bo">Eudora</a> is easy to edit and responsive. It packs a punch in features: a myriad of page templates, a powerful admin panel, unlimited colors, multiple widgets, multiple post formats, Google Web Fonts, multiple portfolio layouts, Google Maps support, video support and SEO-ready features. Created by ThemeProfuse, Eudora is equipped with an impressive options panel for general settings, the slider, navigation, the footer and the blog. It is compatible with major browsers.</p> <p><a href="http://eudora.designprefix.com/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/11-Eudora.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Avino</h1> <p><a href="http://avino.wsblogz.com/" rel="nofollow external" class="bo">Avino</a> is a responsive theme with a powerful options page and unlimited home page layouts, which is an advantage for those looking to develop a unique layout. Created by WSGraphic, Avino is designed for any business, although photographers and those in tech and consulting would especially reap its benefits because it is clean, minimalist and responsive. In addition, the theme has a built-in SEO plugin.</p> <p><a href="http://avino.wsblogz.com/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/12.-Avino.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Helios</h1> <p><a href="http://wp-demo.indonez.com/?theme=Helios" rel="nofollow external" class="bo">Helios</a> comes in two styles: boxed and wide. Its minimalist, responsive design gives it an edge. And it incorporates valid HTML5 and PSD files. The theme is compatible with major browsers and comes with an advanced options page. Created by Indonez, Helios’ settings panel has options for general settings, fonts and the logo. Additional features are Google Web Fonts support, two blog page layouts, custom page templates, an AJAX contact form, and translation-ready capabilities.</p> <p><a href="http://wp-demo.indonez.com/?theme=Helios" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/13.-Helios.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>Grider</h1> <p><a href="http://wpthemes.iweb-studio.com/grider/" rel="nofollow external" class="bo">Grider</a> is a responsive corporate theme that allows you to pick any color from a color picker. Pick also from multiple page templates, including for the home page and contact page, as well as a full-width template. Created by iWebStudio, Grider also comes with a myriad of other attributes: elastic slider, flex slider, skitter slider, multiple shortcodes, translation-ready capabilities, and an under-construction template with a countdown. The theme is compatible with internet Explorer 10+, Firefox, Safari, Chrome and Opera.</p> <p><a href="http://wpthemes.iweb-studio.com/grider/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/14.-Grider.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a></p> <p> </p> <h1>TouchM</h1> <p><a href="http://themes.forgrafx.com/?theme=TouchM-WP" rel="nofollow external" class="bo">TouchM</a> is beautifully crafted. Apart from being viewable on any device, TouchM comes with unlimited color and font capabilities. Its advanced panel helps you set preferences for the header, main content, body, menu and footer. Created by 4GraFx, TouchM comes with full integration with WooCommerce, an e-commerce toolkit. It also features 404 and under-construction page templates, which are not included in most WordPress themes nowadays. It also features a visual shortcode generator, multiple icons and more than 20 page layouts.</p> <p><a href="http://themes.forgrafx.com/?theme=TouchM-WP" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/15.-TouchM.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Architecture</h1> <p><a href="http://themes.goodlayers.com/?theme=architecture" rel="nofollow external" class="bo">Architecture</a> is a beautiful theme with a responsive design. The name of the theme gives away its target industry: architecture. And its minimal and contemporary look and feel are appropriate to it. It also features a live color changer and is compatible with most browsers. Created by Good Layers, the theme comes with an advanced options panel for colors, sliders, fonts, the favicon, Google Analytics, the footer, the portfolio and the body. Other features are a built-in translator and built-in shortcodes.</p> <p><a href="http://themes.goodlayers.com/?theme=architecture" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/16.-Architecture.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Lawyer</h1> <p>Do not be fooled by the name. <a href="http://preview.ait-themes.com/index.php?bartype=desktop&amp;theme=lawyer" rel="nofollow external" class="bo">Lawyer</a> is designed for all types of businesses. However, lawyers will reap the most benefit. It is attractive and Retina-ready, has unlimited colors through a color picker and is compatible with internet Explorer 8 and 9, Firefox, Chrome and Safari. Created by AitThemes, Lawyers comes with an easy-to-use admin panel for colors, images, widgets, sliders, portfolios, galleries and more. The theme also features practical shortcodes, multiple tools and accessories.</p> <p><a href="http://preview.ait-themes.com/index.php?bartype=desktop&amp;theme=lawyer" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/17.-Lawyer.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Maximus</h1> <p>Want to know what you can tweak easily with the <a href="http://www.themes.dynamicpress.eu/?theme=maximus" rel="nofollow external" class="bo">Maximus</a> WordPress theme? Here is just a brief list: the main accent color, page layout, theme color, social icon positioning, home page slider, general slider, content, navigation, and layout. Created by Dynamic Press, Maximus supports most browsers and comes with a custom skin creator, more than 100 shortcodes, multiple background patterns and SEO support.</p> <p><a href="http://www.themes.dynamicpress.eu/?theme=maximus" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/18.-Maximus.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Camouflet</h1> <p>One of the outstanding features of <a href="http://wpthemes.iweb-studio.com/camouflet/" rel="nofollow external" class="bo">Camouflet</a> its responsiveness, not to mention that it is clean and minimalist. With the options panel, you can upload your own background image and change colors. Created by iWebStudios, Camouflet makes it easy for users to style many elements with shortcodes, including for columns, drop caps, lists, dividers, block quotes, testimonials, pricing boxes, buttons, information boxes, accordions, tabs, YouTube and Vimeo videos and Google maps.</p> <p><a href="http://wpthemes.iweb-studio.com/camouflet/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/19.-Camouflet.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>CoolBlue</h1> <p><a href="http://anpsthemes.com/coolblue/" rel="nofollow external" class="bo">CoolBlue</a> is a responsive theme that comes with an amazing layer slider, unlimited colors and an advanced options panel. Created by Anps Themes, CoolBlue is also compatible with internet Explorer 8 and 9, Firefox, Safari and Opera. Additional features include a set of 500+ Google Web Fonts, unlimited sidebars, multiple shortcodes, 30 PSD files and multiple blog layouts. True to its name, it comes with relaxing color schemes, different icon shapes, different layout styles and the all-amazing Revolution Slider.</p> <p><a href="http://anpsthemes.com/coolblue/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/20.-CoolBlue.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Ageless</h1> <p><a href="http://themes.damojothemes.com/?theme=ageless_wp" rel="nofollow external" class="bo">Ageless</a> is a modern WordPress 3.5+-compatible theme. It is responsive, translation-ready and HTML5-ready. Ageless is also flawless on most browsers, including Firefox, Safari, Opera, internet Explorer 8 and 9, and Chrome. Created by Damojo, it incorporates smart options for styles and colors, and it features unlimited sidebars, unlimited portfolios, custom widgets, multiple post formats, localization capabilities, customizable contact forms and multiple shortcodes.</p> <p><a href="http://themes.damojothemes.com/?theme=ageless_wp" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/21.-Ageless.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>WP Consultant</h1> <p><a href="http://themes.contempographicdesign.com/?theme=consultant" rel="nofollow external" class="bo">WP Consultant</a> is a premium theme suitable for all types of businesses. Coded in HTML5 and CSS3, it is fully responsive and comes with free updates for life (making your website dynamic and responsive and building trust with your customers). Created by Contempoinc, the theme packs many features: multiple page templates (including for testimonials, site map and FAQ), full width pages, three-column pages, a client page, contact page and several home page styles. The theme is also equipped with a powerful page builder.</p> <p><a href="http://themes.contempographicdesign.com/?theme=consultant" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/22.-WP-Consultant.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Impact</h1> <p><a href="http://www.wpexplorer.me/premium/impact/" rel="nofollow external" class="bo">Impact</a> is a fully responsive WordPress theme. Built with HTML5 and CSS3, it has some of the best WordPress functions built in, making for an easy-to-use and simply awesome theme. It is compatible with WordPress 3.5+ and comes with multiple color options. Created by WpExplorer, this theme is compatible with the most browsers. And the creator also offers reliable support and updates.</p> <p><a href="http://www.wpexplorer.me/premium/impact/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/23.-Impact.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Vanguard</h1> <p><a href="http://vanguard.unispheredesign.com/" rel="nofollow external" class="bo">Vanguard</a> is a clean, responsive theme with unlimited color capabilities. Created by Unisphere, the corporate theme comes with 500+ fonts, which you can add to. It is compatible with internet Explorer 8 and 9, Safari, Firefox and Chrome, has both wide and narrow layouts, and has an advanced options panel.</p> <p><a href="http://vanguard.unispheredesign.com/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/24.-Vanguard.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>November</h1> <p><a href="http://theme.phowebstudio.com/november/" rel="nofollow external" class="bo">November</a> is an amazing premium theme. It comes with a wide array of features, one of the most impressive of which is the page builder, which allows you to build pages by dragging and dropping. Another is the Revolution Slider, which you get free of charge, a $30 value. Created by PWvintage, this WordPress 3.5+ theme is compatible with major browsers and comes equipped with Google Web Fonts, unlimited color capabilities, an advanced options page and multiple customizable slider transitions.</p> <p><a href="http://theme.phowebstudio.com/november/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/25.-November.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Savior Business</h1> <p><a href="http://demo.scheetzdesigns.com/savior-business/" rel="nofollow external" class="bo">Savior Business</a> is a powerful theme. It is responsive and comes in two styles: light and dark. It even includes a calendar with recurring events. The theme also has goodies in the form of the Nivo slider, which is provided for free. Created by Justin Scheetz, this theme is ideal for any business. It is compatible with major browsers and incorporates custom widgets, shortcodes and an options panel.</p> <p><a href="http://demo.scheetzdesigns.com/savior-business/" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/26.-Savior-Business.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Sirius</h1> <p><a href="http://wp-demo.indonez.com/?theme=Sirius" rel="nofollow external" class="bo">Sirius</a> is a modern, minimalist theme. Newbies and advanced users will have an easy time using this theme. In addition to being responsive, it comes with a wide array of features. Created by Indonez, the theme features thumbnail support with dynamic image resizing, custom page templates, shortcodes and a powerful options panel. Mainstream browsers are supported.</p> <p><a href="http://wp-demo.indonez.com/?theme=Sirius" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/27.-Sirius.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>OpenSpace</h1> <p><a href="http://www.themes.dynamicpress.eu/?theme=openspace" rel="nofollow external" class="bo">OpenSpace</a> is also a responsive theme, supported by WordPress 3.0+. It would suit any industry, particularly photography. One feature that stands out is the admin panel, which is fully brandable and comes with multiple color schemes. Created by Dynamic Press, OpenSpace is compatible with internet Explorer 7 to 9, Safari, Firefox, Chrome and Opera. It comes with multiple patterns, a multicolored menu, custom skin creator, multiple sliders and shortcodes, as well as two layouts: fluid and boxed.</p> <p><a href="http://www.themes.dynamicpress.eu/?theme=openspace" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/28.-OpenSpace.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>Brandspace</h1> <p><a href="http://demo.pixelentity.com/?brandspace_wp" rel="nofollow external" class="bo">Brandspace</a> is a responsive theme that supports WordPress 3.4+. It comes with unlimited color capabilities, chosen from a powerful options panel and is compatible with most browsers. Created by Pixel Entity, the theme comes with a set of awesome attributes: Google Web Fonts, Google maps, oodles of shortcodes, light and dark skins, Twitter Bootstrap, unlimited widget areas, unlimited portfolios, child theme support, built-in social media, video support, and multiple page types.</p> <p><a href="http://demo.pixelentity.com/?brandspace_wp" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/29.-Brandspace.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <h1>BlueDiamond</h1> <p><a href="http://themes.goodlayers.com/?theme=bluediamond" rel="nofollow external" class="bo">BlueDiamond</a> is clean, minimalist and responsive. It is equipped with the Layer Slider, which allows you to manage all sliders with an easy drag-and-drop module. It also comes with two styles: boxed and wide. Created by Good Layers, Blue Diamond supports internet Explorer 8 and 9, Chrome, Safari and Firefox. From its advanced options panel, you can configure the slider settings, the background, thumbnails, the page builder and social media.</p> <p><a href="http://themes.goodlayers.com/?theme=bluediamond" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2013/02/30.-Blue-Diamond.jpg" width="650" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"></a> </p> <p> </p> <p><em><strong>What do you look for in a WordPress business theme? Have we missed any of your favorites? Let us know in the comments.</strong></em></p> <p><br><br> </p>
    <table width="100%"> <tbody>
    <tr> <td> <a href="http://www.mightydeals.com/deal/vandelay-mobile-design-bundle.html?ref=inwidget" rel="nofollow external" class="bo"><strong>The Ultimate Mobile Design Resource Bundle – only $29!</strong></a> </td> <td> <a href="http://www.mightydeals.com/?ref=inwidget" rel="nofollow external" class="bo"><br> <img src="http://mightydeals.com/web/images/widget-logo.png" height="40" width="90" alt="30 fresh WordPress business themes" style="max-width: 100%; height: auto;"><br> </a> </td> </tr> </tbody>
    </table> <p><br> </p> <a href="http://www.webdesignerdepot.com/2013/06/30-fresh-wordpress-business-themes/" rel="nofollow external" class="bo">Source</a> <div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F06%2F30-fresh-wordpress-business-themes%2F&amp;t=30+fresh+WordPress+business+themes" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F06%2F30-fresh-wordpress-business-themes%2F&amp;t=30+fresh+WordPress+business+themes" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F06%2F30-fresh-wordpress-business-themes%2F&amp;t=30+fresh+WordPress+business+themes" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F06%2F30-fresh-wordpress-business-themes%2F&amp;t=30+fresh+WordPress+business+themes" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F06%2F30-fresh-wordpress-business-themes%2F&amp;t=30+fresh+WordPress+business+themes" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/165665167452/u/49/f/661066/c/35285/s/2d475b2d/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/165665167452/u/49/f/661066/c/35285/s/2d475b2d/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Most of the time, the first contact a customer will have with your business is through your website. Consequently, the website could make or break your business. To ensure that the website makes...</Summary>
<Website>http://rss.feedsportal.com/c/35285/f/661066/s/2d475b2d/l/0L0Swebdesignerdepot0N0C20A130C0A60C30A0Efresh0Ewordpress0Ebusiness0Ethemes0C/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31314/guest@my.umbc.edu/0cb2bcedb8d9f96c62670857269f0a06/api/pixel</TrackingUrl>
<Tag>art</Tag>
<Tag>best-business-themes-for-wordpress</Tag>
<Tag>best-wordpress-themes</Tag>
<Tag>business-themes</Tag>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>html5</Tag>
<Tag>illustrator</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>oracle</Tag>
<Tag>photoshop</Tag>
<Tag>php</Tag>
<Tag>resources</Tag>
<Tag>sql</Tag>
<Tag>wordpress</Tag>
<Tag>wordpress-themes-roundup</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 14 Jun 2013 05:15:30 -0400</PostedAt>
<EditAt>Fri, 14 Jun 2013 05:15:30 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="31312" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31312">
<Title>Study Gauges Value of Technology in Schools</Title>
<Body>
<![CDATA[
    <div class="html-content">A review of federal data found that technology investments in schools had not changed the nature of education.<div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Feducation%2Fstudy-gauges-value-of-technology-in-schools.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Study+Gauges+Value+of+Technology+in+Schools" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Feducation%2Fstudy-gauges-value-of-technology-in-schools.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Study+Gauges+Value+of+Technology+in+Schools" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Feducation%2Fstudy-gauges-value-of-technology-in-schools.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Study+Gauges+Value+of+Technology+in+Schools" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Feducation%2Fstudy-gauges-value-of-technology-in-schools.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Study+Gauges+Value+of+Technology+in+Schools" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Feducation%2Fstudy-gauges-value-of-technology-in-schools.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Study+Gauges+Value+of+Technology+in+Schools" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/165666064557/u/0/f/640387/c/34625/s/2d44535d/kg/342-363/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/165666064557/u/0/f/640387/c/34625/s/2d44535d/kg/342-363/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>A review of federal data found that technology investments in schools had not changed the nature of education.     </Summary>
<Website>http://www.nytimes.com/2013/06/14/education/study-gauges-value-of-technology-in-schools.html?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31312/guest@my.umbc.edu/e614ef4f6609cd97f57d4cc25c792e00/api/pixel</TrackingUrl>
<Tag>computers-and-the-internet</Tag>
<Tag>e-learning</Tag>
<Tag>education-k-12</Tag>
<Tag>mathematics</Tag>
<Tag>national-assessment-of-educational-progress</Tag>
<Tag>new</Tag>
<Tag>technology</Tag>
<Tag>tests-and-examinations</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Thu, 13 Jun 2013 21:57:49 -0400</PostedAt>
<EditAt>Thu, 13 Jun 2013 21:57:49 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="31311" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31311">
<Title>Secret Court Ruling Put Tech Companies in Data Bind</Title>
<Body>
<![CDATA[
    <div class="html-content">In 2008, a ruling by a surveillance court said to be against Yahoo discouraged technology firms from fighting data requests from the government.<div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fsecret-court-ruling-put-tech-companies-in-data-bind.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Secret+Court+Ruling+Put+Tech+Companies+in+Data+Bind" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fsecret-court-ruling-put-tech-companies-in-data-bind.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Secret+Court+Ruling+Put+Tech+Companies+in+Data+Bind" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fsecret-court-ruling-put-tech-companies-in-data-bind.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Secret+Court+Ruling+Put+Tech+Companies+in+Data+Bind" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fsecret-court-ruling-put-tech-companies-in-data-bind.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Secret+Court+Ruling+Put+Tech+Companies+in+Data+Bind" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fsecret-court-ruling-put-tech-companies-in-data-bind.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Secret+Court+Ruling+Put+Tech+Companies+in+Data+Bind" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/165665519613/u/0/f/640387/c/34625/s/2d43b192/kg/342-363/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/165665519613/u/0/f/640387/c/34625/s/2d43b192/kg/342-363/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>In 2008, a ruling by a surveillance court said to be against Yahoo discouraged technology firms from fighting data requests from the government.     </Summary>
<Website>http://www.nytimes.com/2013/06/14/technology/secret-court-ruling-put-tech-companies-in-data-bind.html?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31311/guest@my.umbc.edu/de939642bff0a2480b86c24bf51f05bf/api/pixel</TrackingUrl>
<Tag>facebook-inc-fb-nasdaq</Tag>
<Tag>foreign-intelligence-surveillance-act-fisa</Tag>
<Tag>google-inc-goog-nasdaq</Tag>
<Tag>microsoft-corporation-msft-nasdaq</Tag>
<Tag>new</Tag>
<Tag>privacy</Tag>
<Tag>surveillance-of-citizens-by-government</Tag>
<Tag>technology</Tag>
<Tag>twitter</Tag>
<Tag>yahoo-inc-yhoo-nasdaq</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Thu, 13 Jun 2013 21:50:32 -0400</PostedAt>
<EditAt>Fri, 14 Jun 2013 21:25:05 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="31309" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31309">
<Title>Combining Laravel 4 and Backbone</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <a href="http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=31745&amp;c=525163202" rel="nofollow external" class="bo"><img src="http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=31745&amp;c=525163202" alt="" style="max-width: 100%; height: auto;"></a><p>For this tutorial, we’re going to be building a single page app using <a href="http://laravel.com/" rel="nofollow external" class="bo">Laravel 4</a> and <a href="http://backbonejs.org/" rel="nofollow external" class="bo">Backbone.js</a>. Both frameworks make it very easy to use a different templating engine other than their respective default, so we’re going to use Mustache, which is an engine that is common to both. By using the same templating language on both sides of our application, we’ll be able to share our views betweem them, saving us from having to repeat our work multiple times.</p>
    <p></p>
    <p>Our Backbone app will be powered by a Laravel 4 JSON API which we’ll develop together. Laravel 4 comes with some new features that make the development of this API very easy. I’ll show you a few tricks along the way to allow you to stay a bit more organized.</p>
    <p>All of our dependencies will be managed by Package Managers, there will be no manual downloading or updating of libraries for this application! In addition, I’ll be showing you how to leverage a little extra power from some of our dependencies.</p>
    <p>For this project we’ll be using:</p>
    <ul>
    <li>
    <a href="http://four.laravel.com" rel="nofollow external" class="bo">Laravel 4</a>: A great PHP framework.</li>
    <li>
    <a href="https://github.com/bobthecow/mustache.php" rel="nofollow external" class="bo">Mustache.php</a>: The PHP rendering engine for <a href="http://mustache.github.io/" rel="nofollow external" class="bo">Mustache</a>.</li>
    <li>
    <a href="https://github.com/janl/mustache.js/" rel="nofollow external" class="bo">Mustache.js</a>: The JavaScript rendering engine for <a href="http://mustache.github.io/" rel="nofollow external" class="bo">Mustache</a>.</li>
    <li>
    <a href="https://github.com/JeffreyWay/Laravel-4-Generators" rel="nofollow external" class="bo">Jeffrey Way's Generators for Laravel 4</a>: We can improve our workflow by generating some boilerplate code for us using these generators.</li>
    <li>
    <a href="http://twitter.github.io/bootstrap/" rel="nofollow external" class="bo">Twitter Bootstrap</a>: A front-end library to aid in our styling.</li>
    <li>
    <a href="https://github.com/sebastianbergmann/phpunit/" rel="nofollow external" class="bo">PHPUnit</a>: A PHP testing suite.</li>
    <li>
    <a href="https://github.com/padraic/mockery" rel="nofollow external" class="bo">Mockery</a>: Used for mocking PHP Objects while testing.</li>
    <li>
    <a href="http://backbonejs.org/" rel="nofollow external" class="bo">Backbone.js</a>: A Javascript MVC for our single page app.</li>
    <li>
    <a href="http://underscorejs.org/" rel="nofollow external" class="bo">Underscore.js</a>: A dependency of Backbone, and a great little toolkit of functions.</li>
    </ul>
    <p>To complete this tutorial, you’ll need the following items installed:</p>
    <ul>
    <li>
    <a href="http://getcomposer.org/" rel="nofollow external" class="bo">Composer</a>: You can download this from the homepage, I recommend the global install instructions located <a href="http://getcomposer.org/doc/00-intro.md#globally" rel="nofollow external" class="bo">here</a>.</li>
    <li>
    <a href="http://nodejs.org/" rel="nofollow external" class="bo">Node + NPM</a>: the installer on the homepage will install both items.</li>
    <li>
    <a href="http://lesscss.org/" rel="nofollow external" class="bo">LESS Compiler</a>: If you’re on a Mac, I recommend CodeKit. However, regardless of your operating system, or if you do not feel like paying for CodeKit, you can just install the LESS Compiler for Node.js by typing <code>npm install -g less</code> at the command prompt.</li>
    </ul>
    <hr>
    <h2>Part 1: The Base Architecture</h2>
    <p>First things first, we need to get our application setup before we can begin adding our business logic to it. We’ll do a basic setup of Laravel 4 and get all of our dependencies installed using our Package Managers.</p>
    <h3>Git</h3>
    <p>Let's start by creating a git repository to work in. For your reference, this entire repo will be made publicly available at <a href="https://github.com/conarwelsh/nettuts-laravel4-and-backbone" rel="nofollow external" class="bo">https://github.com/conarwelsh/nettuts-laravel4-and-backbone</a>.</p>
    <pre>mkdir project &amp;&amp; cd project&#x000A;    git init&#x000A;    </pre>
    <h3>Laravel 4 Installation</h3>
    <p>Laravel 4 uses Composer to install all of its dependencies, but first we’ll need an application structure to install into. The “develop” branch on <a href="https://github.com/laravel/laravel" rel="nofollow external" class="bo">Laravel's Github repository</a> is the home for this application structure. However, at the time of writing this article, Laravel 4 was still in beta, so I needed to be prepared for this structure to change at any time. By adding Laravel as a remote repository, we can pull in these changes whenever we need to. In fact, while something is in beta-mode, it’s a good practice to run these commands after each <code>composer update</code>. However, Laravel 4 is now the newest, stable version.</p>
    <pre>git remote add laravel <a href="https://github.com/laravel/laravel">https://github.com/laravel/laravel</a>&#x000A;    git fetch laravel&#x000A;    git merge laravel/develop&#x000A;    git add . &amp;&amp; git commit -am "commit the laravel application structure"&#x000A;    </pre>
    <p>So we have the application structure, but all of the library files that Laravel needs are not yet installed. You’ll notice at the root of our application there’s a file called <code>composer.json</code>. This is the file that will keep track of all the dependencies that our Laravel application requires. Before we tell Composer to download and install them, let's first add a few more dependencies that we’re going to need. We’ll be adding:</p>
    <ul>
    <li>
    <a href="https://packagist.org/packages/way/generators" rel="nofollow external" class="bo">Jeffrey Way's Generators</a>: Some very useful commands to greatly improve our workflow by automatically generating file stubs for us.</li>
    <li>
    <a href="https://packagist.org/packages/conarwelsh/mustache-l4" rel="nofollow external" class="bo">Laravel 4 Mustache</a>: This will allow us to seamlessly use Mustache.php in our Laravel project, just as we would Blade.</li>
    <li>
    <a href="https://packagist.org/packages/twitter/bootstrap" rel="nofollow external" class="bo">Twitter Bootstrap</a>: We’ll use the LESS files from this project to speed up our front-end development.</li>
    <li>
    <a href="https://packagist.org/packages/phpunit/phpunit" rel="nofollow external" class="bo">PHPUnit</a>: We’ll be doing some TDD for our JSON API, PHPUnit will be our testing engine.</li>
    <li>
    <a href="https://packagist.org/packages/mockery/mockery" rel="nofollow external" class="bo">Mockery</a>: Mockery will help us "mock" objects during our testing.</li>
    </ul>
    <p>PHPUnit and Mockery are only required in our development environment, so we’ll specify that in our composer.json file.</p>
    <hr>
    <p><strong>composer.json</strong></p>
    <pre>{&#x000A;      "require": {&#x000A;        "laravel/framework": "4.0.*",&#x000A;        "way/generators": "dev-master",&#x000A;        "twitter/bootstrap": "dev-master",&#x000A;        "conarwelsh/mustache-l4": "dev-master"&#x000A;      },&#x000A;      "require-dev": {&#x000A;        "phpunit/phpunit": "3.7.*",&#x000A;        "mockery/mockery": "0.7.*"&#x000A;      },&#x000A;      "autoload": {&#x000A;        "classmap": [&#x000A;          "app/commands",&#x000A;          "app/controllers",&#x000A;          "app/models",&#x000A;          "app/database/migrations",&#x000A;          "app/database/seeds",&#x000A;          "app/tests/TestCase.php"&#x000A;        ]&#x000A;      },&#x000A;      "scripts": {&#x000A;        "post-update-cmd": "php artisan optimize"&#x000A;      },&#x000A;      "minimum-stability": "dev"&#x000A;    }&#x000A;    </pre>
    <p>Now we just need to tell Composer to do all of our leg work! Below, notice the <code>--dev</code> switch, we’re telling composer that we’re in our development environment and that it should also install all of our dependencies listed in <code>"require-dev"</code>.</p>
    <pre>composer install --dev&#x000A;    </pre>
    <p>After that finishes installing, we’ll need to inform Laravel of a few of our dependencies. Laravel uses "service providers" for this purpose. These service providers basically just tell Laravel how their code is going to interact with the application and to run any necessary setup procedures. Open up <code>app/config/app.php</code> and add the following two items to the "<code>providers</code>" array. Not all packages require this, only those that will enhance or change the functionality of Laravel.</p>
    <hr>
    <p><strong>app/config/app.php</strong></p>
    <pre>...&#x000A;    &#x000A;    'Way\Generators\GeneratorsServiceProvider',&#x000A;    'Conarwelsh\MustacheL4\MustacheL4ServiceProvider',&#x000A;    &#x000A;    ...&#x000A;    </pre>
    <p>Lastly, we just need to do some generic application tweaks to complete our Laravel installation. Let's open up <code>bootstrap/start.php</code> and tell Laravel our machine name so that it can determine what environment it’s in.</p>
    <hr>
    <p><strong>bootstrap/start.php</strong></p>
    <pre>/*&#x000A;    |--------------------------------------------------------------------------&#x000A;    | Detect The Application Environment&#x000A;    |--------------------------------------------------------------------------&#x000A;    |&#x000A;    | Laravel takes a dead simple approach to your application environments&#x000A;    | so you can just specify a machine name or HTTP host that matches a&#x000A;    | given environment, then we will automatically detect it for you.&#x000A;    |&#x000A;    */&#x000A;    &#x000A;    $env = $app-&gt;detectEnvironment(array(&#x000A;    &#x000A;      'local' =&gt; array('your-machine-name'),&#x000A;    &#x000A;    ));&#x000A;    </pre>
    <p>Replace "your-machine-name" with whatever the hostname for your machine is. If you are unsure of what your exact machine name is, you can just type <code>hostname</code> at the command prompt (on Mac or Linux), whatever it prints out is the value that belongs in this setting.</p>
    <p>We want our views to be able to be served to our client from a web request. Currently, our views are stored outside of our <code>public</code> folder, which would mean that they are <em>not</em> publicly accessible. Luckily, Laravel makes it very easy to move or add other view folders. Open up <code>app/config/view.php</code> and change the <code>paths</code> setting to point to our public folder. This setting works like the PHP native include path, it will check in each folder until it finds a matching view file, so feel free to add several here:</p>
    <hr>
    <p><strong>app/config/view.php</strong></p>
    <pre>'paths' =&gt; array(__DIR__.'/../../public/views'),&#x000A;    </pre>
    <p>Next you will need to configure your database. Open up <code>app/config/database.php</code> and add in your database settings.</p>
    <p>Note: It is recommended to use <code>127.0.0.1</code> instead of <code>localhost</code>. You get a bit of a performance boost on most systems, and with some system configurations, <code>localhost</code> will not even connect properly.</p>
    <p>Finally, you just need to make sure that your storage folder is writable.</p>
    <pre>chmod -R 755 app/storage&#x000A;    </pre>
    <p>Laravel is now installed, with all of its dependencies, as well as our own dependencies. Now let's setup our Backbone installation!</p>
    <p>Just like our <code>composer.json</code> installed all of our server-side dependencies, we’ll create a <code>package.json</code> in our <em>public folder</em> to install all of our client-side dependencies.</p>
    <p>For our client-side dependencies we’ll use:</p>
    <ul>
    <li>
    <a href="https://npmjs.org/package/underscore" rel="nofollow external" class="bo">Underscore.js</a>: This is a dependency of Backbone.js, and a handy toolbelt of functions.</li>
    <li>
    <a href="https://npmjs.org/package/backbone" rel="nofollow external" class="bo">Backbone.js</a>: This is our client-side MVC that we’ll use to build out our application.</li>
    <li>
    <a href="https://npmjs.org/package/mustache" rel="nofollow external" class="bo">Mustache.js</a>: The Javascript version of our templating library, by using the same templating language both on the client and the server, we can share views, as opposed to duplicating logic.</li>
    </ul>
    <hr>
    <p><strong>public/package.json</strong></p>
    <pre>{&#x000A;      "name": "nettuts-laravel4-and-backbone",&#x000A;      "version": "0.0.1",&#x000A;      "private": true,&#x000A;      "dependencies": {&#x000A;        "underscore": "*",&#x000A;        "backbone": "*",&#x000A;        "mustache": "*"&#x000A;      }&#x000A;    }&#x000A;    </pre>
    <p>Now just switch into your public folder, and run <code>npm install</code>. After that completes, lets switch back to our application root so we’re prepared for the rest of our commands.</p>
    <pre>cd public&#x000A;    npm install&#x000A;    cd ..&#x000A;    </pre>
    <p>Package managers save us from a ton of work, should you want to update any of these libraries, all you have to do is run <code>npm update</code> or <code>composer update</code>. Also, should you want to lock any of these libraries in at a specific version, all you have to do is specify the version number, and the package manager will handle the rest.</p>
    <p>To wrap up our setup process we’ll just add in all of the basic project files and folders that we’ll need, and then test it out to ensure it all works as expected.</p>
    <p>We’ll need to add the following folders:</p>
    <ul>
    <li>public/views</li>
    <li>public/views/layouts</li>
    <li>public/js</li>
    <li>public/css</li>
    </ul>
    <p>And the following files:</p>
    <ul>
    <li>public/css/styles.less</li>
    <li>public/js/app.js</li>
    <li>public/views/app.mustache</li>
    </ul>
    <p>To accomplish this, we can use a one-liner:</p>
    <pre>mkdir public/views public/views/layouts public/js public/css &amp;&amp; touch public/css/styles.less public/js/app.js public/views/app.mustache&#x000A;    </pre>
    <p>Twitter Bootstrap also has two JavaScript dependencies that we’ll need, so let's just copy them from the vendor folder into our public folder. They are:</p>
    <ul>
    <li>
    <strong>html5shiv.js</strong>: allows us to use HTML5 elements without fear of older browsers not supporting them</li>
    <li>
    <strong>bootstrap.min.js</strong>: the supporting JavaScript libraries for Twitter Bootstrap</li>
    </ul>
    <pre>cp vendor/twitter/bootstrap/docs/assets/js/html5shiv.js public/js/html5shiv.js&#x000A;    cp vendor/twitter/bootstrap/docs/assets/js/bootstrap.min.js public/js/bootstrap.min.js&#x000A;    </pre>
    <p>For our layout file, the Twitter Bootstrap also provides us with some nice starter templates to work with, so let's copy one into our layouts folder for a head start:</p>
    <pre>cp vendor/twitter/bootstrap/docs/examples/starter-template.html public/views/layouts/application.blade.php&#x000A;    </pre>
    <blockquote><p>Notice that I am using a blade extension here, this could just as easily be a mustache template, but I wanted to show you how easy it is to mix the templating engines. Since our layout will be rendered on page load, and will not need to be re-rendered by the client, we are safe to use PHP here exclusively. If for some reason you find yourself needing to render this file on the client-side, you would want to switch this file to use the Mustache templating engine instead.</p></blockquote>
    <p>Now that we have all of our basic files in place, let's add some starter content that we can use to test that everything is working as we would expect. I’m providing you with some basic stubs to get you started.</p>
    <hr>
    <p><strong>public/css/styles.less</strong></p>
    <p>We’ll just import the Twitter Bootstrap files from the vendor directory as opposed to copying them. This allows us to update Twitter Bootstrap with nothing but a <code>composer update</code>.</p>
    <p>We declare our variables at the end of the file, the LESS compiler will figure out the value of all of its variables before parsing the LESS into CSS. This means that by re-defining a Twitter Bootstrap variable at the end of the file, the value will actually change for all of the files included, allowing us to do simple overrides without modifying the Twitter Bootstrap core files.</p>
    <pre>/**&#x000A;     * Import Twitter Bootstrap Base File&#x000A;     ******************************************************************************************&#x000A;     */&#x000A;    @import "../../vendor/twitter/bootstrap/less/bootstrap";&#x000A;    /**&#x000A;     * Define App Styles&#x000A;     * Do this before the responsive include, so that it can override properly as needed.&#x000A;     ******************************************************************************************&#x000A;     */&#x000A;    body {&#x000A;      padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */&#x000A;    }&#x000A;    &#x000A;    /* this will set the position of our alerts */&#x000A;    #notifications {&#x000A;      width: 300px;&#x000A;      position: fixed;&#x000A;      top: 50px;&#x000A;      left: 50%;&#x000A;      margin-left: -150px;&#x000A;      text-align: center;&#x000A;    }&#x000A;    &#x000A;    /**&#x000A;     * Import Bootstrap's Responsive Overrides&#x000A;     * now we allow bootstrap to set the overrides for a responsive layout&#x000A;     ******************************************************************************************&#x000A;     */&#x000A;    @import "../../vendor/twitter/bootstrap/less/responsive";&#x000A;    /**&#x000A;     * Define our variables last, any variable declared here will be used in the includes above&#x000A;     * which means that we can override any of the variables used in the bootstrap files easily&#x000A;     * without modifying any of the core bootstrap files&#x000A;     ******************************************************************************************&#x000A;     */&#x000A;    &#x000A;    // Scaffolding&#x000A;    // -------------------------&#x000A;    @bodyBackground:    #f2f2f2;&#x000A;    @textColor:       #575757;&#x000A;    &#x000A;    // Links&#x000A;    // -------------------------&#x000A;    @linkColor:       #41a096;&#x000A;    &#x000A;    // Typography&#x000A;    // -------------------------&#x000A;    @sansFontFamily:    Arial, Helvetica, sans-serif;&#x000A;    </pre>
    <hr>
    <p><strong>public/js/app.js</strong></p>
    <p>Now we’ll wrap all of our code in an immediately-invoking-anonymous-function that passes in a few global objects. We’ll then alias these global objects to something more useful to us. Also, we’ll cache a few jQuery objects inside the document ready function.</p>
    <pre>//alias the global object&#x000A;    //alias jQuery so we can potentially use other libraries that utilize $&#x000A;    //alias Backbone to save us on some typing&#x000A;    (function(exports, $, bb){&#x000A;    &#x000A;      //document ready&#x000A;      $(function(){&#x000A;    &#x000A;        /**&#x000A;         ***************************************&#x000A;         * Cached Globals&#x000A;         ***************************************&#x000A;         */&#x000A;        var $window, $body, $document;&#x000A;    &#x000A;        $window  = $(window);&#x000A;        $document = $(document);&#x000A;        $body   = $('body');&#x000A;      });//end document ready&#x000A;    &#x000A;    }(this, jQuery, Backbone));&#x000A;    </pre>
    <hr>
    <p><strong>public/views/layouts/application.blade.php</strong></p>
    <p>Next is just a simple HTML layout file. We’re however using the <code>asset</code> helper from Laravel to aid us in creating paths to our assets. It is good practice to use this type of helper, because if you ever happen to move your project into a sub-folder, all of your links will still work.</p>
    <p>We made sure that we included all of our dependencies in this file, and also added the jQuery dependency. I chose to request jQuery from the Google CDN, because chances are the visiting user of this site will already have a copy from that CDN cached in their browser, saving us from having to complete the HTTP request for it.</p>
    <p>One important thing to note here is the way in which we are nesting our view. Mustache does not have Block Sections like Blade does, so instead, the contents of the nested view will be made available under a variable with the name of the section. I will point this out when we render this view from our route.</p>
    <pre>&lt;!DOCTYPE html&gt;&#x000A;    &lt;html lang="en"&gt;&#x000A;    &lt;head&gt;&#x000A;     &lt;meta charset="utf-8"&gt;&#x000A;     &lt;title&gt;Laravel4 &amp; Backbone | Nettuts&lt;/title&gt;&#x000A;     &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;&#x000A;     &lt;meta name="description" content="A single page blog built using Backbone.js, Laravel, and Twitter Bootstrap"&gt;&#x000A;     &lt;meta name="author" content="Conar Welsh"&gt;&#x000A;    &#x000A;     &lt;link href="{{ asset('css/styles.css') }}" rel="stylesheet"&gt;&#x000A;    &#x000A;     &lt;!-- HTML5 shim, for IE6-8 support of HTML5 elements --&gt;&#x000A;     &lt;!--[if lt IE 9]&gt;&#x000A;     &lt;script src="{{ asset('js/html5shiv.js') }}"&gt;&lt;/script&gt;&#x000A;     &lt;![endif]--&gt;&#x000A;    &lt;/head&gt;&#x000A;    &lt;body&gt;&#x000A;    &#x000A;     &lt;div id="notifications"&gt;&#x000A;     &lt;/div&gt;&#x000A;    &#x000A;     &lt;div class="navbar navbar-inverse navbar-fixed-top"&gt;&#x000A;      &lt;div class="navbar-inner"&gt;&#x000A;       &lt;div class="container"&gt;&#x000A;        &lt;button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"&gt;&#x000A;         &lt;span class="icon-bar"&gt;&lt;/span&gt;&#x000A;         &lt;span class="icon-bar"&gt;&lt;/span&gt;&#x000A;         &lt;span class="icon-bar"&gt;&lt;/span&gt;&#x000A;        &lt;/button&gt;&#x000A;        &lt;a class="brand" href="#"&gt;Nettuts Tutorial&lt;/a&gt;&#x000A;        &lt;div class="nav-collapse collapse"&gt;&#x000A;         &lt;ul class="nav"&gt;&#x000A;          &lt;li class="active"&gt;&lt;a href="#"&gt;Blog&lt;/a&gt;&lt;/li&gt;&#x000A;         &lt;/ul&gt;&#x000A;        &lt;/div&gt;&lt;!--/.nav-collapse --&gt;&#x000A;       &lt;/div&gt;&#x000A;      &lt;/div&gt;&#x000A;     &lt;/div&gt;&#x000A;    &#x000A;     &lt;div class="container" data-role="main"&gt;&#x000A;      {{--since we are using mustache as the view, it does not have a concept of sections like blade has, so instead of using @yield here, our nested view will just be a variable that we can echo--}}&#x000A;    &#x000A;      {{ $content }}&#x000A;    &#x000A;     &lt;/div&gt; &lt;!-- /container --&gt;&#x000A;    &#x000A;     &lt;!-- Placed at the end of the document so the pages load faster --&gt;&#x000A;     &lt;script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"&gt;&lt;/script&gt; &lt;!-- use Google CDN for jQuery to hopefully get a cached copy --&gt;&#x000A;     &lt;script src="{{ asset('node_modules/underscore/underscore-min.js') }}"&gt;&lt;/script&gt;&#x000A;     &lt;script src="{{ asset('node_modules/backbone/backbone-min.js') }}"&gt;&lt;/script&gt;&#x000A;     &lt;script src="{{ asset('node_modules/mustache/mustache.js') }}"&gt;&lt;/script&gt;&#x000A;     &lt;script src="{{ asset('js/bootstrap.min.js') }}"&gt;&lt;/script&gt;&#x000A;     &lt;script src="{{ asset('js/app.js') }}"&gt;&lt;/script&gt;&#x000A;     @yield('scripts')&#x000A;    &lt;/body&gt;&#x000A;    &lt;/html&gt;&#x000A;    </pre>
    <hr>
    <p><strong>public/views/app.mustache</strong></p>
    <p>Next is just a simple view that we’ll nest into our layout.</p>
    <pre>&lt;dl&gt;&#x000A;      &lt;dt&gt;Q. What did Biggie say when he watched inception?&lt;/dt&gt;&#x000A;      &lt;dd&gt;A. "It was all a dream!"&lt;/dd&gt;&#x000A;    &lt;/dl&gt;&#x000A;    </pre>
    <hr>
    <p><strong>app/routes.php</strong></p>
    <p>Laravel should have already provided you with a default route, all we’re doing here is changing the name of the view which that route is going to render.</p>
    <p>Remember from above, I told you that the nested view was going to be available under a variable named whatever the parent section was? Well, when you nest a view, the first parameter to the function is the section name:</p>
    <pre>View::make('view.path')-&gt;nest($sectionName, $nestedViewPath, $viewVariables);&#x000A;    </pre>
    <p>In our <code>nest</code> command we called the section "content", that means if we echo <code>$content</code> from our layout, we’ll get the rendered contents of that view. If we were to do <code>return View::make('layouts.application')-&gt;nest('foobar', 'app');</code> then our nested view would be available under a variable named <code>$foobar</code>.</p>
    <pre>&lt;?php&#x000A;    &#x000A;    //backbone app route&#x000A;    Route::get('/', function()&#x000A;    {&#x000A;      //change our view name to the view we created in a previous step&#x000A;      //notice that we do not need to provide the .mustache extension&#x000A;      return View::make('layouts.application')-&gt;nest('content', 'app');&#x000A;    });&#x000A;    </pre>
    <p>With all of our basic files in place, we can test to ensure everything went OK. Laravel 4 utilizes the new PHP web server to provide us with a great little development environment. So long to the days of having a million virtual hosts setup on your development machine for every project that you work on!</p>
    <blockquote><p>Note: make sure that you’ve compiled your LESS file first!</p></blockquote>
    <pre>php artisan serve&#x000A;    </pre>
    <p>If you followed along correctly, you should be laughing hysterically at my horrible sense of humor, and all of our assets should be properly included into the page.</p>
    <hr>
    <h2>Part 2: Laravel 4 JSON API</h2>
    <p>Now we’ll build the API that will power our Backbone application. Laravel 4 makes this process a breeze.</p>
    <h3>API Guidelines</h3>
    <p>First let's go over a few general guidelines to keep in mind while we build our API:</p>
    <ul>
    <li>
    <p><strong>Status Codes</strong>: Responses should reply with proper status codes, fight the temptation to just place an <code>{ error: "this is an error message" }</code> in the body of your response. Use the HTTP protocol to its fullest!</p>
    <ul>
    <li>
    <strong>200</strong>: success</li>
    <li>
    <strong>201</strong>: resource created</li>
    <li>
    <strong>204</strong>: success, but no content to return</li>
    <li>
    <strong>400</strong>: request not fulfilled //validation error</li>
    <li>
    <strong>401</strong>: not authenticated</li>
    <li>
    <strong>403</strong>: refusal to respond //wrong credentials, do not have permission (un-owned resource)</li>
    <li>
    <strong>404</strong>: not found</li>
    <li>
    <strong>500</strong>: other error</li>
    </ul>
    </li>
    <li>
    <p><strong>Resource Methods</strong>: Even though controllers will be serving different resources, they should still have very similar behavior. The more predictable your API is, the easier it is to implement and adopt.</p>
    <ul>
    <li>
    <strong>index</strong>: Return a collection of resources.</li>
    <li>
    <strong>show</strong>: Return a single resource.</li>
    <li>
    <strong>create</strong>: Return a form. This form should detail out the required fields, validation, and labels as best as possible. As well as anything else needed to properly create a resource. Even though this is a JSON API, it is very useful to return a form here. Both a computer and a person can parse through this form, and very easily decipher which items are needed to fill out this form successsfully. This is a very easy way to “document” the needs of your API.</li>
    <li>
    <strong>store</strong>: Store a new resource and return with the proper status code: 201.</li>
    <li>
    <strong>edit</strong>: Return a form filled with the current state of a resource. This form should detail out the required fields, validation, and labels as best as possible. As well as anything else needed to properly edit a resource.</li>
    <li>
    <strong>update</strong>: Update an existing resource and return with the proper status code.</li>
    <li>
    <strong>delete</strong>: Delete an existing resource and return with the proper status code: 204.</li>
    </ul>
    </li>
    </ul>
    <h3>Routing &amp; Versioning</h3>
    <p>API's are designed to be around for a while. This is not like your website where you can just change its functionality at the drop of a dime. If you have programs that use your API, they are not going to be happy with you if you change things around and their program breaks. For this reason, it’s important that you use versioning.</p>
    <p>We can always create a "version two" with additional, or altered functionality, and allow our subscribing programs to opt-in to these changes, rather than be forced.</p>
    <p>Laravel provides us with route groups that are perfect for this, place the following code <em>ABOVE</em> our first route:</p>
    <pre>&lt;?php&#x000A;    &#x000A;    //create a group of routes that will belong to APIv1&#x000A;    Route::group(array('prefix' =&gt; 'v1'), function()&#x000A;    {&#x000A;      //... insert API routes here...&#x000A;    });&#x000A;    </pre>
    <h3>Generating Resources</h3>
    <p>We’re going to use Jeffrey Way's generators to generate our resources. When we generate a resource, it will create the following items for us:</p>
    <ul>
    <li>Controller</li>
    <li>Model</li>
    <li>Views (index.blade.php, show.blade.php, create.blade.php, edit.blade.php)</li>
    <li>Migration</li>
    <li>Seeds</li>
    </ul>
    <p>We’re only going to need two resources for this app: a <code>Post</code> resource and a <code>Comment</code> resource.</p>
    <p>Note: in a recent update to the generators, I have been receiving a permissions error due to the way my web servers are setup. To remedy this problem, you must allow write permissions to the folder that the generators write the temp file to.</p>
    <pre>sudo chmod -R 755 vendor/way/generators/src/Way/&#x000A;    </pre>
    <p>Run the <code>generate:resource</code> command</p>
    <pre>php artisan generate:resource post --fields="title:string, content:text, author_name:string"&#x000A;    &#x000A;    php artisan generate:resource comment --fields="content:text, author_name:string, post_id:integer"&#x000A;    </pre>
    <p>You should now pause for a second to investigate all of the files that the generator created for us.</p>
    <h3>Adjust the Generated Resources</h3>
    <p>The <code>generate:resource</code> command saved us a lot of work, but due to our unique configuration, we’re still going to need to make some modifications.</p>
    <p>First of all, the generator placed the views it created in the <code>app/views</code> folder, so we need to move them to the <code>public/views</code> folder</p>
    <pre>mv app/views/posts public/views/posts&#x000A;    mv app/views/comments public/views/comments&#x000A;    </pre>
    <hr>
    <p><strong>app/routes.php</strong></p>
    <p>We decided that we wanted our API to be versioned, so we’ll need to move the routes that the generator created for us into the version group. We’ll also want to namespace our controllers with the corresponding version, so that we can have a different set of controllers for each version we build. Also the comments resource needs to be nested under the posts resource.</p>
    <pre>&lt;?php&#x000A;    &#x000A;    //create a group of routes that will belong to APIv1&#x000A;    Route::group(array('prefix' =&gt; 'v1'), function()&#x000A;    {&#x000A;      //... insert API routes here...&#x000A;      Route::resource('posts', 'V1\PostsController'); //notice the namespace&#x000A;      Route::resource('posts.comments', 'V1\PostsCommentsController'); //notice the namespace, and the nesting&#x000A;    });&#x000A;    &#x000A;    //backbone app route&#x000A;    Route::get('/', function()&#x000A;    {&#x000A;      //change our view name to the view we created in a previous step&#x000A;      //notice that we do not need to provide the .mustache extension&#x000A;      return View::make('layouts.application')-&gt;nest('content', 'app');&#x000A;    });&#x000A;    </pre>
    <p>Since we namespaced our controllers, we should move them into their own folder for organization, let's create a folder named <code>V1</code> and move our generated controllers into it. Also, since we nested our comments controller under the posts controller, let's change the name of that controller to reflect the relationship.</p>
    <pre>mkdir app/controllers/V1&#x000A;    mv app/controllers/PostsController.php app/controllers/V1/&#x000A;    mv app/controllers/CommentsController.php app/controllers/V1/PostsCommentsController.php&#x000A;    </pre>
    <p>We’ll need to update the controller files to reflect our changes as well. First of all, we need to namespace them, and since they are namespaced, any classes outside of that namespace will need to be manually imported with the <code>use</code> statement.</p>
    <p><strong>app/controllers/PostsController.php</strong></p>
    <pre>&lt;?php&#x000A;    //use our new namespace&#x000A;    namespace V1;&#x000A;    &#x000A;    //import classes that are not in this new namespace&#x000A;    use BaseController;&#x000A;    &#x000A;    class PostsController extends BaseController {&#x000A;    </pre>
    <p><strong>app/controllers/PostsCommentsController.php</strong></p>
    <p>We also need to update our <code>CommentsController</code> with our new name: <code>PostsCommentsController</code></p>
    <pre>&lt;?php&#x000A;    //use our new namespace&#x000A;    namespace V1;&#x000A;    &#x000A;    //import classes that are not in this new namespace&#x000A;    use BaseController;&#x000A;    &#x000A;    //rename our controller class&#x000A;    class PostsCommentsController extends BaseController {&#x000A;    </pre>
    <h3>Adding in Repositories</h3>
    <p>By default, repositories are not part of Laravel. Laravel is extremely flexible though, and makes it very easy to add them in. We’re going to use repositories to help us separate our logic for code re-usability, as well as for testing. For now we’ll just get setup to use repositories, we’ll add in the proper logic later.</p>
    <p>Let’s make a folder to store our repositories in:</p>
    <pre>mkdir app/repositories&#x000A;    </pre>
    <p>To let our auto-loader know about this new folder, we need to add it to our <code>composer.json</code> file. Take a look at the updated "autoload" section of our file, and you’ll see that we added in the repositories folder.</p>
    <p><strong>composer.json</strong></p>
    <pre>{&#x000A;      "require": {&#x000A;        "laravel/framework": "4.0.*",&#x000A;        "way/generators": "dev-master",&#x000A;        "twitter/bootstrap": "dev-master",&#x000A;        "conarwelsh/mustache-l4": "dev-master"&#x000A;      },&#x000A;      "require-dev": {&#x000A;        "phpunit/phpunit": "3.7.*",&#x000A;        "mockery/mockery": "0.7.*"&#x000A;      },&#x000A;      "autoload": {&#x000A;        "classmap": [&#x000A;          "app/commands",&#x000A;          "app/controllers",&#x000A;          "app/models",&#x000A;          "app/database/migrations",&#x000A;          "app/database/seeds",&#x000A;          "app/tests/TestCase.php",&#x000A;          "app/repositories"&#x000A;        ]&#x000A;      },&#x000A;      "scripts": {&#x000A;        "post-update-cmd": "php artisan optimize"&#x000A;      },&#x000A;      "minimum-stability": "dev"&#x000A;    }&#x000A;    </pre>
    <h3>Seeding Our Database</h3>
    <p>Database seeds are a useful tool, they provide us with an easy way to fill our database with some content. The generators provided us with base files for seeding, we merely need to add in some actual seeds.</p>
    <p><strong>app/database/seeds/PostsTableSeeder.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    class PostsTableSeeder extends Seeder {&#x000A;    &#x000A;      public function run()&#x000A;      {&#x000A;        $posts = array(&#x000A;          array(&#x000A;            'title'    =&gt; 'Test Post',&#x000A;            'content'   =&gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',&#x000A;            'author_name' =&gt; 'Conar Welsh',&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;          array(&#x000A;            'title'    =&gt; 'Another Test Post',&#x000A;            'content'   =&gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',&#x000A;            'author_name' =&gt; 'Conar Welsh',&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;        );&#x000A;    &#x000A;        // Uncomment the below to run the seeder&#x000A;        DB::table('posts')-&gt;insert($posts);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p><strong>app/database/seeds/CommentsTableSeeder.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    class CommentsTableSeeder extends Seeder {&#x000A;    &#x000A;      public function run()&#x000A;      {&#x000A;        $comments = array(&#x000A;          array(&#x000A;            'content'   =&gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',&#x000A;            'author_name' =&gt; 'Testy McTesterson',&#x000A;            'post_id'   =&gt; 1,&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;          array(&#x000A;            'content'   =&gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',&#x000A;            'author_name' =&gt; 'Testy McTesterson',&#x000A;            'post_id'   =&gt; 1,&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;          array(&#x000A;            'content'   =&gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',&#x000A;            'author_name' =&gt; 'Testy McTesterson',&#x000A;            'post_id'   =&gt; 2,&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;        );&#x000A;    &#x000A;        // Uncomment the below to run the seeder&#x000A;        DB::table('comments')-&gt;insert($comments);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p>Don’t forget to run <code>composer dump-autoload</code> to let the Composer auto loader know about the new migration files!</p>
    <pre>composer dump-autoload&#x000A;    </pre>
    <p>Now we can run our migrations and seed the database. Laravel provides us with a single command to do both:</p>
    <pre>php artisan migrate --seed&#x000A;    </pre>
    <h3>Tests</h3>
    <p>Testing is one of those topics in development that no one can argue the importance of, however most people tend to ignore it due to the learning curve. Testing is really not that difficult and it can dramatically improve your application. For this tutorial, we’ll setup some basic tests to help us ensure that our API is functioning properly. We’ll build this API TDD style. The rules of TDD state that we are not allowed to write any production code until we have failing tests that warrants it. However, if I were to walk you through each test individually, this would prove to be a very long tutorial, so in the interest of brevity, I will just provide you with some tests to work from, and then the correct code to make those tests pass afterwards.</p>
    <p>Before we write any tests though, we should first check the current test status of our application. Since we installed PHPUnit via composer, we have the binaries available to us to use. All you need to do is run:</p>
    <pre>vendor/phpunit/phpunit/phpunit.php&#x000A;    </pre>
    <p>Whoops! We already have a failure! The test that is failing is actually an example test that comes pre-installed in our Laravel application structure, this tests against the default route that was also installed with the Laravel application structure. Since we modified this route, we cannot be surprised that the test failed. We can however, just delete this test altogether as it does not apply to our application.</p>
    <pre>rm app/tests/ExampleTest.php&#x000A;    </pre>
    <p>If you run the PHPUnit command again, you will see that no tests were executed, and we have a clean slate for testing.</p>
    <blockquote><p>Note: it is possible that if you have an older version of Jeffrey Way's generators that you’ll actually have a few tests in there that were created by those generators, and those tests are probably failing. Just delete or overwrite those tests with the ones found below to proceed.</p></blockquote>
    <p>For this tutorial we’ll be testing our controllers and our repositories. Let's create a few folders to store these tests in:</p>
    <pre>mkdir app/tests/controllers app/tests/repositories&#x000A;    </pre>
    <p>Now for the test files. We’re going to use Mockery to mock our repositories for our controller tests. Mockery objects do as their name implies, they "mock" objects and report back to us on how those objects were interacted with.</p>
    <p>In the case of the controller tests, we do not actually want the repositories to be called, after all, these are the controller tests, not the repository tests. So Mockery will set us up objects to use <em>instead</em> of our repositories, and let us know whether or not those objects were called as we expected them to.</p>
    <p>In order to pull this off, we’ll have to tell the controllers to use our "mocked" objects as opposed to the real things. We’ll just tell our Application to use a mocked instance next time a certain class is requested. The command looks like this:</p>
    <pre>App::instance($classToReplace, $instanceOfClassToReplaceWith);&#x000A;    </pre>
    <p>The overall mocking process will go something like this:</p>
    <ul>
    <li>Create a new Mockery object, providing it the name of the class which it is to mock.</li>
    <li>Tell the Mockery object which methods it should expect to receive, how many times it should receive that method, and what that method should return.</li>
    <li>Use the command shown above to tell our Application to use this new Mockery object instead of the default.</li>
    <li>Run the controller method like usual.</li>
    <li>Assert the response.</li>
    </ul>
    <p><strong>app/tests/controllers/CommentsControllerTest.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    class CommentsControllerTest extends TestCase {&#x000A;    &#x000A;      /**&#x000A;       ************************************************************************&#x000A;       * Basic Route Tests&#x000A;       * notice that we can use our route() helper here!&#x000A;       ************************************************************************&#x000A;       */&#x000A;    &#x000A;      //test that GET /v1/posts/1/comments returns HTTP 200&#x000A;      public function testIndex()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.index', array(1)) );&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      //test that GET /v1/posts/1/comments/1 returns HTTP 200&#x000A;      public function testShow()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.show', array(1,1)) );&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      //test that GET /v1/posts/1/comments/create returns HTTP 200&#x000A;      public function testCreate()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.create', array(1)) );&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      //test that GET /v1/posts/1/comments/1/edit returns HTTP 200&#x000A;      public function testEdit()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.edit', array(1,1)) );&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       *************************************************************************&#x000A;       * Tests to ensure that the controller calls the repo as we expect&#x000A;       * notice we are "Mocking" our repository&#x000A;       *&#x000A;       * also notice that we do not really care about the data or interactions&#x000A;       * we merely care that the controller is doing what we are going to want&#x000A;       * it to do, which is reach out to our repository for more information&#x000A;       *************************************************************************&#x000A;       */&#x000A;    &#x000A;      //ensure that the index function calls our repository's "findAll" method&#x000A;      public function testIndexShouldCallFindAllMethod()&#x000A;      {&#x000A;        //create our new Mockery object with a name of CommentRepositoryInterface&#x000A;        $mock = Mockery::mock('CommentRepositoryInterface');&#x000A;    &#x000A;        //inform the Mockery object that the "findAll" method should be called on it once&#x000A;        //and return a string value of "foo"&#x000A;        $mock-&gt;shouldReceive('findAll')-&gt;once()-&gt;andReturn('foo');&#x000A;    &#x000A;        //inform our application that we have an instance that it should use&#x000A;        //whenever the CommentRepositoryInterface is requested&#x000A;        App::instance('CommentRepositoryInterface', $mock);&#x000A;    &#x000A;        //call our controller route&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.index', array(1)));&#x000A;    &#x000A;        //assert that the response is a boolean value of true&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      //ensure that the show method calls our repository's "findById" method&#x000A;      public function testShowShouldCallFindById()&#x000A;      {&#x000A;        $mock = Mockery::mock('CommentRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('findById')-&gt;once()-&gt;andReturn('foo');&#x000A;        App::instance('CommentRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.show', array(1,1)));&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      //ensure that our create method calls the "instance" method on the repository&#x000A;      public function testCreateShouldCallInstanceMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('CommentRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('instance')-&gt;once()-&gt;andReturn(array());&#x000A;        App::instance('CommentRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.create', array(1)));&#x000A;        $this-&gt;assertViewHas('comment');&#x000A;      }&#x000A;    &#x000A;      //ensure that the edit method calls our repository's "findById" method&#x000A;      public function testEditShouldCallFindByIdMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('CommentRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('findById')-&gt;once()-&gt;andReturn(array());&#x000A;        App::instance('CommentRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('GET', route('v1.posts.comments.edit', array(1,1)));&#x000A;        $this-&gt;assertViewHas('comment');&#x000A;      }&#x000A;    &#x000A;      //ensure that the store method should call the repository's "store" method&#x000A;      public function testStoreShouldCallStoreMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('CommentRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('store')-&gt;once()-&gt;andReturn('foo');&#x000A;        App::instance('CommentRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('POST', route('v1.posts.comments.store', array(1)));&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      //ensure that the update method should call the repository's "update" method&#x000A;      public function testUpdateShouldCallUpdateMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('CommentRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('update')-&gt;once()-&gt;andReturn('foo');&#x000A;        App::instance('CommentRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('PUT', route('v1.posts.comments.update', array(1,1)));&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      //ensure that the destroy method should call the repositories "destroy" method&#x000A;      public function testDestroyShouldCallDestroyMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('CommentRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('destroy')-&gt;once()-&gt;andReturn(true);&#x000A;        App::instance('CommentRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('DELETE', route('v1.posts.comments.destroy', array(1,1)));&#x000A;        $this-&gt;assertTrue( empty($response-&gt;original) );&#x000A;      }&#x000A;    }&#x000A;    </pre>
    <p><strong>app/tests/controllers/PostsControllerTest.php</strong></p>
    <p>Next, we’ll follow the exact same procedure for the <code>PostsController</code> tests</p>
    <pre>&lt;?php&#x000A;    &#x000A;    class PostsControllerTest extends TestCase {&#x000A;    &#x000A;      /**&#x000A;       * Test Basic Route Responses&#x000A;       */&#x000A;      public function testIndex()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.index'));&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      public function testShow()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.show', array(1)));&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      public function testCreate()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.create'));&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      public function testEdit()&#x000A;      {&#x000A;        $response = $this-&gt;call('GET', route('v1.posts.edit', array(1)));&#x000A;        $this-&gt;assertTrue($response-&gt;isOk());&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Test that controller calls repo as we expect&#x000A;       */&#x000A;      public function testIndexShouldCallFindAllMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('PostRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('findAll')-&gt;once()-&gt;andReturn('foo');&#x000A;        App::instance('PostRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('GET', route('v1.posts.index'));&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      public function testShowShouldCallFindById()&#x000A;      {&#x000A;        $mock = Mockery::mock('PostRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('findById')-&gt;once()-&gt;andReturn('foo');&#x000A;        App::instance('PostRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('GET', route('v1.posts.show', array(1)));&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      public function testCreateShouldCallInstanceMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('PostRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('instance')-&gt;once()-&gt;andReturn(array());&#x000A;        App::instance('PostRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('GET', route('v1.posts.create'));&#x000A;        $this-&gt;assertViewHas('post');&#x000A;      }&#x000A;    &#x000A;      public function testEditShouldCallFindByIdMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('PostRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('findById')-&gt;once()-&gt;andReturn(array());&#x000A;        App::instance('PostRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('GET', route('v1.posts.edit', array(1)));&#x000A;        $this-&gt;assertViewHas('post');&#x000A;      }&#x000A;    &#x000A;      public function testStoreShouldCallStoreMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('PostRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('store')-&gt;once()-&gt;andReturn('foo');&#x000A;        App::instance('PostRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('POST', route('v1.posts.store'));&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      public function testUpdateShouldCallUpdateMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('PostRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('update')-&gt;once()-&gt;andReturn('foo');&#x000A;        App::instance('PostRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('PUT', route('v1.posts.update', array(1)));&#x000A;        $this-&gt;assertTrue(!! $response-&gt;original);&#x000A;      }&#x000A;    &#x000A;      public function testDestroyShouldCallDestroyMethod()&#x000A;      {&#x000A;        $mock = Mockery::mock('PostRepositoryInterface');&#x000A;        $mock-&gt;shouldReceive('destroy')-&gt;once()-&gt;andReturn(true);&#x000A;        App::instance('PostRepositoryInterface', $mock);&#x000A;    &#x000A;        $response = $this-&gt;call('DELETE', route('v1.posts.destroy', array(1)));&#x000A;        $this-&gt;assertTrue( empty($response-&gt;original) );&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <hr>
    <p><strong>app/tests/repositories/EloquentCommentRepositoryTest.php</strong></p>
    <p>Now for the repository tests. In writing our controller tests, we pretty much already decided what most of the interface should look like for the repositories. Our controllers needed the following methods:</p>
    <ul>
    <li>findById($id)</li>
    <li>findAll()</li>
    <li>instance($data)</li>
    <li>store($data)</li>
    <li>update($id, $data)</li>
    <li>destroy($id)</li>
    </ul>
    <p>The only other method that we’ll want to add here is a <code>validate</code> method. This will mainly be a private method for the repository to ensure that the data is safe to store or update.</p>
    <p>For these tests, we’re also going to add a <code>setUp</code> method, which will allow us to run some code on our class, prior to the execution of <em>each</em> test. Our <code>setUp</code> method will be a very simple one, we’ll just make sure that any <code>setUp</code> methods defined in parent classes are also called using <code>parent::setUp()</code> and then simply add a class variable that stores an instance of our repository.</p>
    <p>We’ll use the power of Laravel's IoC container again to get an instance of our repository. The <code>App::make()</code> command will return an instance of the requested class, now it may seem strange that we do not just do <code>$this-&gt;repo = new EloquentCommentRepository()</code>, but hold that thought, we’ll come back to it momentarily. You probably noticed that we’re asking for a class called <code>EloquentCommentRepository</code>, but in our controller tests above, we were calling our repository <code>CommentRepositoryInterface</code>… put this thought on the back-burner as well… explainations for both are coming, I promise!</p>
    <pre>&lt;?php&#x000A;    &#x000A;    class EloquentCommentRepositoryTest extends TestCase {&#x000A;    &#x000A;      public function setUp()&#x000A;      {&#x000A;        parent::setUp();&#x000A;        $this-&gt;repo = App::make('EloquentCommentRepository');&#x000A;      }&#x000A;    &#x000A;      public function testFindByIdReturnsModel()&#x000A;      {&#x000A;        $comment = $this-&gt;repo-&gt;findById(1,1);&#x000A;        $this-&gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);&#x000A;      }&#x000A;    &#x000A;      public function testFindAllReturnsCollection()&#x000A;      {&#x000A;        $comments = $this-&gt;repo-&gt;findAll(1);&#x000A;        $this-&gt;assertTrue($comments instanceof Illuminate\Database\Eloquent\Collection);&#x000A;      }&#x000A;    &#x000A;      public function testValidatePasses()&#x000A;      {&#x000A;        $reply = $this-&gt;repo-&gt;validate(array(&#x000A;          'post_id'   =&gt; 1,&#x000A;          'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',&#x000A;          'author_name' =&gt; 'Testy McTesterson'&#x000A;        ));&#x000A;    &#x000A;        $this-&gt;assertTrue($reply);&#x000A;      }&#x000A;    &#x000A;      public function testValidateFailsWithoutContent()&#x000A;      {&#x000A;        try {&#x000A;          $reply = $this-&gt;repo-&gt;validate(array(&#x000A;            'post_id'   =&gt; 1,&#x000A;            'author_name' =&gt; 'Testy McTesterson'&#x000A;          ));&#x000A;        }&#x000A;        catch(ValidationException $expected)&#x000A;        {&#x000A;          return;&#x000A;        }&#x000A;    &#x000A;        $this-&gt;fail('ValidationException was not raised');&#x000A;      }&#x000A;    &#x000A;      public function testValidateFailsWithoutAuthorName()&#x000A;      {&#x000A;        try {&#x000A;          $reply = $this-&gt;repo-&gt;validate(array(&#x000A;            'post_id'   =&gt; 1,&#x000A;            'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.'&#x000A;          ));&#x000A;        }&#x000A;        catch(ValidationException $expected)&#x000A;        {&#x000A;          return;&#x000A;        }&#x000A;    &#x000A;        $this-&gt;fail('ValidationException was not raised');&#x000A;      }&#x000A;    &#x000A;      public function testValidateFailsWithoutPostId()&#x000A;      {&#x000A;        try {&#x000A;          $reply = $this-&gt;repo-&gt;validate(array(&#x000A;            'author_name' =&gt; 'Testy McTesterson',&#x000A;            'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.'&#x000A;          ));&#x000A;        }&#x000A;        catch(ValidationException $expected)&#x000A;        {&#x000A;          return;&#x000A;        }&#x000A;    &#x000A;        $this-&gt;fail('ValidationException was not raised');&#x000A;      }&#x000A;    &#x000A;      public function testStoreReturnsModel()&#x000A;      {&#x000A;        $comment_data = array(&#x000A;          'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',&#x000A;          'author_name' =&gt; 'Testy McTesterson'&#x000A;        );&#x000A;    &#x000A;        $comment = $this-&gt;repo-&gt;store(1, $comment_data);&#x000A;    &#x000A;        $this-&gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);&#x000A;        $this-&gt;assertTrue($comment-&gt;content === $comment_data['content']);&#x000A;        $this-&gt;assertTrue($comment-&gt;author_name === $comment_data['author_name']);&#x000A;      }&#x000A;    &#x000A;      public function testUpdateSaves()&#x000A;      {&#x000A;        $comment_data = array(&#x000A;          'content' =&gt; 'The Content Has Been Updated'&#x000A;        );&#x000A;    &#x000A;        $comment = $this-&gt;repo-&gt;update(1, 1, $comment_data);&#x000A;    &#x000A;        $this-&gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);&#x000A;        $this-&gt;assertTrue($comment-&gt;content === $comment_data['content']);&#x000A;      }&#x000A;    &#x000A;      public function testDestroySaves()&#x000A;      {&#x000A;        $reply = $this-&gt;repo-&gt;destroy(1,1);&#x000A;        $this-&gt;assertTrue($reply);&#x000A;    &#x000A;        try {&#x000A;          $this-&gt;repo-&gt;findById(1,1);&#x000A;        }&#x000A;        catch(NotFoundException $expected)&#x000A;        {&#x000A;          return;&#x000A;        }&#x000A;    &#x000A;        $this-&gt;fail('NotFoundException was not raised');&#x000A;      }&#x000A;    &#x000A;      public function testInstanceReturnsModel()&#x000A;      {&#x000A;        $comment = $this-&gt;repo-&gt;instance();&#x000A;        $this-&gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);&#x000A;      }&#x000A;    &#x000A;      public function testInstanceReturnsModelWithData()&#x000A;      {&#x000A;        $comment_data = array(&#x000A;          'title' =&gt; 'Un-validated title'&#x000A;        );&#x000A;    &#x000A;        $comment = $this-&gt;repo-&gt;instance($comment_data);&#x000A;        $this-&gt;assertTrue($comment instanceof Illuminate\Database\Eloquent\Model);&#x000A;        $this-&gt;assertTrue($comment-&gt;title === $comment_data['title']);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p><strong>app/tests/repositories/EloquentPostRepositoryTest.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    class EloquentPostRepositoryTest extends TestCase {&#x000A;    &#x000A;      public function setUp()&#x000A;      {&#x000A;        parent::setUp();&#x000A;        $this-&gt;repo = App::make('EloquentPostRepository');&#x000A;      }&#x000A;    &#x000A;      public function testFindByIdReturnsModel()&#x000A;      {&#x000A;        $post = $this-&gt;repo-&gt;findById(1);&#x000A;        $this-&gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);&#x000A;      }&#x000A;    &#x000A;      public function testFindAllReturnsCollection()&#x000A;      {&#x000A;        $posts = $this-&gt;repo-&gt;findAll();&#x000A;        $this-&gt;assertTrue($posts instanceof Illuminate\Database\Eloquent\Collection);&#x000A;      }&#x000A;    &#x000A;      public function testValidatePasses()&#x000A;      {&#x000A;        $reply = $this-&gt;repo-&gt;validate(array(&#x000A;          'title'    =&gt; 'This Should Pass',&#x000A;          'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',&#x000A;          'author_name' =&gt; 'Testy McTesterson'&#x000A;        ));&#x000A;    &#x000A;        $this-&gt;assertTrue($reply);&#x000A;      }&#x000A;    &#x000A;      public function testValidateFailsWithoutTitle()&#x000A;      {&#x000A;        try {&#x000A;          $reply = $this-&gt;repo-&gt;validate(array(&#x000A;            'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',&#x000A;            'author_name' =&gt; 'Testy McTesterson'&#x000A;          ));&#x000A;        }&#x000A;        catch(ValidationException $expected)&#x000A;        {&#x000A;          return;&#x000A;        }&#x000A;    &#x000A;        $this-&gt;fail('ValidationException was not raised');&#x000A;      }&#x000A;    &#x000A;      public function testValidateFailsWithoutAuthorName()&#x000A;      {&#x000A;        try {&#x000A;          $reply = $this-&gt;repo-&gt;validate(array(&#x000A;            'title'    =&gt; 'This Should Pass',&#x000A;            'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.'&#x000A;          ));&#x000A;        }&#x000A;        catch(ValidationException $expected)&#x000A;        {&#x000A;          return;&#x000A;        }&#x000A;    &#x000A;        $this-&gt;fail('ValidationException was not raised');&#x000A;      }&#x000A;    &#x000A;      public function testStoreReturnsModel()&#x000A;      {&#x000A;        $post_data = array(&#x000A;          'title'    =&gt; 'This Should Pass',&#x000A;          'content'   =&gt; 'Lorem ipsum Fugiat consectetur laborum Ut consequat aliqua.',&#x000A;          'author_name' =&gt; 'Testy McTesterson'&#x000A;        );&#x000A;    &#x000A;        $post = $this-&gt;repo-&gt;store($post_data);&#x000A;    &#x000A;        $this-&gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);&#x000A;        $this-&gt;assertTrue($post-&gt;title === $post_data['title']);&#x000A;        $this-&gt;assertTrue($post-&gt;content === $post_data['content']);&#x000A;        $this-&gt;assertTrue($post-&gt;author_name === $post_data['author_name']);&#x000A;      }&#x000A;    &#x000A;      public function testUpdateSaves()&#x000A;      {&#x000A;        $post_data = array(&#x000A;          'title' =&gt; 'The Title Has Been Updated'&#x000A;        );&#x000A;    &#x000A;        $post = $this-&gt;repo-&gt;update(1, $post_data);&#x000A;    &#x000A;        $this-&gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);&#x000A;        $this-&gt;assertTrue($post-&gt;title === $post_data['title']);&#x000A;      }&#x000A;    &#x000A;      public function testDestroySaves()&#x000A;      {&#x000A;        $reply = $this-&gt;repo-&gt;destroy(1);&#x000A;        $this-&gt;assertTrue($reply);&#x000A;    &#x000A;        try {&#x000A;          $this-&gt;repo-&gt;findById(1);&#x000A;        }&#x000A;        catch(NotFoundException $expected)&#x000A;        {&#x000A;          return;&#x000A;        }&#x000A;    &#x000A;        $this-&gt;fail('NotFoundException was not raised');&#x000A;      }&#x000A;    &#x000A;      public function testInstanceReturnsModel()&#x000A;      {&#x000A;        $post = $this-&gt;repo-&gt;instance();&#x000A;        $this-&gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);&#x000A;      }&#x000A;    &#x000A;      public function testInstanceReturnsModelWithData()&#x000A;      {&#x000A;        $post_data = array(&#x000A;          'title' =&gt; 'Un-validated title'&#x000A;        );&#x000A;    &#x000A;        $post = $this-&gt;repo-&gt;instance($post_data);&#x000A;        $this-&gt;assertTrue($post instanceof Illuminate\Database\Eloquent\Model);&#x000A;        $this-&gt;assertTrue($post-&gt;title === $post_data['title']);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p>Now that we have all of our tests in place, let's run PHPUnit again to watch them fail!</p>
    <pre>vendor/phpunit/phpunit/phpunit.php&#x000A;    </pre>
    <p>You should have a whole ton of failures, and in fact, the test suite probably did not even finish testing before it crashed. This is OK, that means we have followed the rules of TDD and wrote failing tests before production code. Although, typically these tests would be written one at a time and you would not move on to the next test until you had code that allowed the previous test to pass. Your terminal should probably look something like mine at the moment:</p> <img src="https://raw.github.com/conarwelsh/nettuts-laravel4-and-backbone/master/public/img/first-failed-screenshot.png" alt="Screenshot" style="max-width: 100%; height: auto;"><p>What’s actually failing is the <code>assertViewHas</code> method in our controller tests. It’s kind of intimidating to deal with this kind of an error when we have lumped together all of our tests without any production code at all. This is why you should always write the tests one at a time, as you’ll find these errors in stride, as opposed to just a huge mess of errors at once. For now, just follow my lead into the implementation of our code.</p>
    <hr>
    <h2>Sidebar Discussion</h2>
    <p>Before we proceed with the implementations, let's break for a quick sidebar discussion on the responsibilities of the MVC pattern.</p>
    <p>From <a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Professional-Computing/dp/0201634988" rel="nofollow external" class="bo">The Gang of Four</a>:</p>
    <blockquote><p>The Model is the application object, the View is its screen presentation, and the Controller defines the way the user interface reacts to user input.</p></blockquote>
    <p>The point of using a structure like this is to remain encapsulated and flexible, allowing us to exchange and reuse components. Let's go through each part of the MVC pattern and talk about its reusability and flexibility:</p>
    <h4>View</h4>
    <p>I think most people would agree that a View is supposed to be a simple visual representation of data and should not contain much logic. In our case, as developers for the web, our View tends to be HTML or XML.</p>
    <ul>
    <li>
    <strong>reusable</strong>: always, almost anything can create a view</li>
    <li>
    <strong>flexible</strong>: not having any real logic in these layers makes this very flexible</li>
    </ul>
    <h4>Controller</h4>
    <p>If a Controller "defines the way the user interface reacts to user input", then its responsibility should be to listen to user input (GET, POST, Headers, etc), and build out the current state of the application. In my opinion, a Controller should be very light and should not contain more code than is required to accomplish the above.</p>
    <ul>
    <li>
    <strong>reusable</strong>: We have to remember that our Controllers return an opinionated View, so we cannot ever call that Controller method in a practical way to use any of the logic inside it. Therefore any logic placed in Controller methods, must be specific to that Controller method, if the logic is reusable, it should be placed elsewhere.</li>
    <li>
    <strong>flexible</strong>: In most PHP MVCs, the Controller is tied directly to the route, which does not leave us very much flexibility. Laravel fixes this issue by allowing us to declare routes that use a controller, so we can now swap out our controllers with different implementations if need be:</li>
    </ul>
    <pre>Route::get('/', array(&#x000A;      'uses' =&gt; 'SomeController@action'&#x000A;    ));&#x000A;    </pre>
    <h4>Model</h4>
    <p>The Model is the "application object" in our definition from the Gang of Four. This is a very generic definition. In addition, we just decided to offload any logic that needs to be reusable from our Controller, and since the Model is the only component left in our defined structure, it’s logical to assume that this is the new home for that logic. However, I think the Model should not contain any logic like this. In my opinion, we should think of our "application object", in this case as an object that represents its place in the data-layer, whether that be a table, row, or collection entirely depends on state. The model should contain not much more than getters and setters for data (including relationships).</p>
    <ul>
    <li>
    <strong>reusable</strong>: If we follow the above practice and make our Models be an object that represents its place in the database, this object remains very reusable. Any part of our system can use this model and by doing so gain complete and unopinionated access to the database.</li>
    <li>
    <strong>flexible</strong>: Following the above practice, our Model is basically an implementation of an ORM, this allows us to be flexible, because we now have the power to change ORM's whenever we’d like to just by adding a new Model. We should probably have a pre-defined interface that our Model's must abide by, such as: all, find, create, update, delete. Implementation of a new ORM would be as simple as ensuring that the previously mentioned interface was accomodated.</li>
    </ul>
    <h4>Repository</h4>
    <p>Just by carefully defining our MVC components, we orphaned all kinds of logic into no-man's land. This is where Repositories come in to fill the void. Repositories become the intermediary of the Controllers and Models. A typical request would be something like this:</p>
    <ul>
    <li>The Controller receives all user input and passes it to the repository.</li>
    <li>The Repository does any "pre-gathering" actions such as validation of data, authorization, authentication, etc. If these "pre-gathering" actions are successful, then the request is passed to the Model for processing.</li>
    <li>The Model will process all of the data into the data-layer, and return the current state.</li>
    <li>The Repository will handle any "post-gathering" routines and return the current state to the controller.</li>
    <li>The Controller will then create the appropriate view using the information provided by the repository.</li>
    </ul>
    <p>Our Repository ends up as flexible and organized as we have made our Controllers and Models, allowing us to reuse this in most parts of our system, as well as being able to swap it out for another implementation if needed.</p>
    <p>We have already seen an example of swapping out a repository for another implementation in the Controller tests above. Instead of using our default Repository, we asked the IoC container to provide the controller with an instance of a Mockery object. We have this same power for all of our components.</p>
    <p>What we have accomplised here by adding another layer to our MVC, is a very organized, scalable, and testable system. Let's start putting the pieces in place and getting our tests to pass.</p>
    <hr>
    <h2>Controller Implementation</h2>
    <p>If you take a read through the controller tests, you’ll see that all we really care about is how the controller is interacting with the repository. So let's see how light and simple that makes our controllers.</p>
    <p>Note: in TDD, the objective is to do no more work than is required to make your tests pass. So we want to do the absolute bare minimum here.</p>
    <p><strong>app/controllers/V1/PostsController.php</strong></p>
    <pre>&lt;?php&#x000A;    namespace V1;&#x000A;    &#x000A;    use BaseController; &#x000A;    use PostRepositoryInterface; &#x000A;    use Input;&#x000A;    use View;&#x000A;    &#x000A;    class PostsController extends BaseController {&#x000A;    &#x000A;      /**&#x000A;       * We will use Laravel's dependency injection to auto-magically&#x000A;       * "inject" our repository instance into our controller&#x000A;       */&#x000A;      public function __construct(PostRepositoryInterface $posts)&#x000A;      {&#x000A;        $this-&gt;posts = $posts;&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Display a listing of the resource.&#x000A;       *&#x000A;       * @return Response&#x000A;       */&#x000A;      public function index()&#x000A;      {&#x000A;        return $this-&gt;posts-&gt;findAll();&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Show the form for creating a new resource.&#x000A;       *&#x000A;       * @return Response&#x000A;       */&#x000A;      public function create()&#x000A;      {&#x000A;        $post = $this-&gt;posts-&gt;instance();&#x000A;        return View::make('posts._form', compact('post'));&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Store a newly created resource in storage.&#x000A;       *&#x000A;       * @return Response&#x000A;       */&#x000A;      public function store()&#x000A;      {&#x000A;        return $this-&gt;posts-&gt;store( Input::all() );&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Display the specified resource.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function show($id)&#x000A;      {&#x000A;        return $this-&gt;posts-&gt;findById($id);&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Show the form for editing the specified resource.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function edit($id)&#x000A;      {&#x000A;        $post = $this-&gt;posts-&gt;findById($id);&#x000A;        return View::make('posts._form', compact('post'));&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Update the specified resource in storage.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function update($id)&#x000A;      {&#x000A;        return $this-&gt;posts-&gt;update($id, Input::all());&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Remove the specified resource from storage.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function destroy($id)&#x000A;      {&#x000A;        $this-&gt;posts-&gt;destroy($id);&#x000A;        return '';&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p><strong>app/controllers/PostsCommentsController.php</strong></p>
    <pre>&lt;?php&#x000A;    namespace V1;&#x000A;    &#x000A;    use BaseController; &#x000A;    use CommentRepositoryInterface; &#x000A;    use Input;&#x000A;    use View;&#x000A;    &#x000A;    class PostsCommentsController extends BaseController {&#x000A;    &#x000A;      /**&#x000A;       * We will use Laravel's dependency injection to auto-magically&#x000A;       * "inject" our repository instance into our controller&#x000A;       */&#x000A;      public function __construct(CommentRepositoryInterface $comments)&#x000A;      {&#x000A;        $this-&gt;comments = $comments;&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Display a listing of the resource.&#x000A;       *&#x000A;       * @return Response&#x000A;       */&#x000A;      public function index($post_id)&#x000A;      {&#x000A;        return $this-&gt;comments-&gt;findAll($post_id);&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Show the form for creating a new resource.&#x000A;       *&#x000A;       * @return Response&#x000A;       */&#x000A;      public function create($post_id)&#x000A;      {&#x000A;        $comment = $this-&gt;comments-&gt;instance(array(&#x000A;          'post_id' =&gt; $post_id&#x000A;        ));&#x000A;    &#x000A;        return View::make('comments._form', compact('comment'));&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Store a newly created resource in storage.&#x000A;       *&#x000A;       * @return Response&#x000A;       */&#x000A;      public function store($post_id)&#x000A;      {&#x000A;        return $this-&gt;comments-&gt;store( $post_id, Input::all() );&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Display the specified resource.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function show($post_id, $id)&#x000A;      {&#x000A;        return $this-&gt;comments-&gt;findById($post_id, $id);&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Show the form for editing the specified resource.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function edit($post_id, $id)&#x000A;      {&#x000A;        $comment = $this-&gt;comments-&gt;findById($post_id, $id);&#x000A;    &#x000A;        return View::make('comments._form', compact('comment'));&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Update the specified resource in storage.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function update($post_id, $id)&#x000A;      {&#x000A;        return $this-&gt;comments-&gt;update($post_id, $id, Input::all());&#x000A;      }&#x000A;    &#x000A;      /**&#x000A;       * Remove the specified resource from storage.&#x000A;       *&#x000A;       * @param int $id&#x000A;       * @return Response&#x000A;       */&#x000A;      public function destroy($post_id, $id)&#x000A;      {&#x000A;        $this-&gt;comments-&gt;destroy($post_id, $id);&#x000A;        return '';&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p>It doesn’t get much simpler than that, all the Controllers are doing is handing the input data to the repository, taking the response from that, and handing it to the View, the View in our case is merely JSON for most of our methods. When we return an Eloquent Collection, or Eloquent Model from a Controller in Laravel 4, the object is parsed into JSON auto-magically, which makes our job very easy.</p>
    <blockquote><p>Note: notice that we added a few more "use" statements to the top of the file to support the other classes that we’re using. Do not forget this when you’re working within a namespace.</p></blockquote>
    <p>The only thing that is a bit tricky in this controller is the constructor. Notice we’re passing in a typed variable as a dependency for this Controller, yet there is no point that we have access to the instantiation of this controller to actually insert that class… welcome to dependency injection! What we’re actually doing here is hinting to our controller that we have a dependency needed to run this class and what its class name is (or its IoC binding name). Laravel uses <code>App::make()</code> to create its Controllers before calling them. <code>App::make()</code> will try to resolve an item by looking for any bindings that we may have declared, and/or using the auto-loader to provide an instance. In addition, it will also resolve any dependencies needed to instantiate that class for us, by more-or-less recursively calling <code>App::make()</code> on each of the dependencies.</p>
    <p>The observant, will notice that what we’re trying to pass in as a dependency is an interface, and as you know, an interface cannot be instantiated. This is where it gets cool and we actually already did the same thing in our tests. In our tests however, we used <code>App::instance()</code> to provide an already created instance instead of the interface. For our Controllers, we’re actually going to tell Laravel that whenever an instance of <code>PostRepositoryInterface</code> is requested, to actually return an instance of <code>EloquentPostRepository</code>.</p>
    <p>Open up your <code>app/routes.php</code> file and add the following to the top of the file</p>
    <pre>App::bind('PostRepositoryInterface', 'EloquentPostRepository');&#x000A;    App::bind('CommentRepositoryInterface', 'EloquentCommentRepository');&#x000A;    </pre>
    <p>After adding those lines, anytime <code>App::make()</code> asks for an instance of <code>PostRepositoryInterface</code>, it will create an instance of <code>EloquentPostRepository</code>, which is assumed to implement <code>PostRepositoryInterface</code>. If you were to ever change your repository to instead use a different ORM than Eloquent, or maybe a file-based driver, all you have to do is change these two lines and you’re good to go, your Controllers will still work as normal. The Controllers actual dependency is any object that implements that interface and we can determine at run-time what that implementation actually is.</p>
    <p>The <code>PostRepositoryInterface</code> and <code>CommentRepositoryInterface</code> must actually exist and the bindings must actually implement them. So let's create them now:</p>
    <p><strong>app/repositories/PostRepositoryInterface.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    interface PostRepositoryInterface {&#x000A;      public function findById($id);&#x000A;      public function findAll();&#x000A;      public function paginate($limit = null);&#x000A;      public function store($data);&#x000A;      public function update($id, $data);&#x000A;      public function destroy($id);&#x000A;      public function validate($data);&#x000A;      public function instance();&#x000A;    }&#x000A;    </pre>
    <p><strong>app/repositories/CommentRepositoryInterface.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    interface CommentRepositoryInterface {&#x000A;      public function findById($post_id, $id);&#x000A;      public function findAll($post_id);&#x000A;      public function store($post_id, $data);&#x000A;      public function update($post_id, $id, $data);&#x000A;      public function destroy($post_id, $id);&#x000A;      public function validate($data);&#x000A;      public function instance();&#x000A;    }&#x000A;    </pre>
    <p>Now that we have our two interfaces built, we must provide implementations of these interfaces. Let's build them now.</p>
    <p><strong>app/repositories/EloquentPostRepository.php</strong></p>
    <p>As the name of this implementation implies, we’re relying on Eloquent, which we can call directly. If you had other dependencies, remember that <code>App::make()</code> is being used to resolve this repository, so you can feel free to use the same constructor method we used with our Controllers to inject your dependencies.</p>
    <pre>&lt;?php&#x000A;    &#x000A;    class EloquentPostRepository implements PostRepositoryInterface {&#x000A;    &#x000A;      public function findById($id)&#x000A;      {&#x000A;        $post = Post::with(array(&#x000A;            'comments' =&gt; function($q)&#x000A;            {&#x000A;              $q-&gt;orderBy('created_at', 'desc');&#x000A;            }&#x000A;          ))&#x000A;          -&gt;where('id', $id)&#x000A;          -&gt;first();&#x000A;    &#x000A;        if(!$post) throw new NotFoundException('Post Not Found');&#x000A;        return $post;&#x000A;      }&#x000A;    &#x000A;      public function findAll()&#x000A;      {&#x000A;        return Post::with(array(&#x000A;            'comments' =&gt; function($q)&#x000A;            {&#x000A;              $q-&gt;orderBy('created_at', 'desc');&#x000A;            }&#x000A;          ))&#x000A;          -&gt;orderBy('created_at', 'desc')&#x000A;          -&gt;get();&#x000A;      }&#x000A;    &#x000A;      public function paginate($limit = null)&#x000A;      {&#x000A;        return Post::paginate($limit);&#x000A;      }&#x000A;    &#x000A;      public function store($data)&#x000A;      {&#x000A;        $this-&gt;validate($data);&#x000A;        return Post::create($data);&#x000A;      }&#x000A;    &#x000A;      public function update($id, $data)&#x000A;      {&#x000A;        $post = $this-&gt;findById($id);&#x000A;        $post-&gt;fill($data);&#x000A;        $this-&gt;validate($post-&gt;toArray());&#x000A;        $post-&gt;save();&#x000A;        return $post;&#x000A;      }&#x000A;    &#x000A;      public function destroy($id)&#x000A;      {&#x000A;        $post = $this-&gt;findById($id);&#x000A;        $post-&gt;delete();&#x000A;        return true;&#x000A;      }&#x000A;    &#x000A;      public function validate($data)&#x000A;      {&#x000A;        $validator = Validator::make($data, Post::$rules);&#x000A;        if($validator-&gt;fails()) throw new ValidationException($validator);&#x000A;        return true;&#x000A;      }&#x000A;    &#x000A;      public function instance($data = array())&#x000A;      {&#x000A;        return new Post($data);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p><strong>app/repositories/EloquentCommentRepository.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    class EloquentCommentRepository implements CommentRepositoryInterface {&#x000A;    &#x000A;      public function findById($post_id, $id)&#x000A;      {&#x000A;        $comment = Comment::find($id);&#x000A;        if(!$comment || $comment-&gt;post_id != $post_id) throw new NotFoundException('Comment Not Found');&#x000A;        return $comment;&#x000A;      }&#x000A;    &#x000A;      public function findAll($post_id)&#x000A;      {&#x000A;        return Comment::where('post_id', $post_id)&#x000A;          -&gt;orderBy('created_at', 'desc')&#x000A;          -&gt;get();&#x000A;      }&#x000A;    &#x000A;      public function store($post_id, $data)&#x000A;      {&#x000A;        $data['post_id'] = $post_id;&#x000A;        $this-&gt;validate($data);&#x000A;        return Comment::create($data);&#x000A;      }&#x000A;    &#x000A;      public function update($post_id, $id, $data)&#x000A;      {&#x000A;        $comment = $this-&gt;findById($post_id, $id);&#x000A;        $comment-&gt;fill($data);&#x000A;        $this-&gt;validate($comment-&gt;toArray());&#x000A;        $comment-&gt;save();&#x000A;        return $comment;&#x000A;      }&#x000A;    &#x000A;      public function destroy($post_id, $id)&#x000A;      {&#x000A;        $comment = $this-&gt;findById($post_id, $id);&#x000A;        $comment-&gt;delete();&#x000A;        return true;&#x000A;      }&#x000A;    &#x000A;      public function validate($data)&#x000A;      {&#x000A;        $validator = Validator::make($data, Comment::$rules);&#x000A;        if($validator-&gt;fails()) throw new ValidationException($validator);&#x000A;        return true;&#x000A;      }&#x000A;    &#x000A;      public function instance($data = array())&#x000A;      {&#x000A;        return new Comment($data);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p>If you take a look in our repositories, there are a few Exceptions that we are throwing, which are not native, nor do they belong to Laravel. Those are custom Exceptions that we’re using to simplify our code. By using custom Exceptions, we’re able to easily halt the progress of the application if certain conditions are met. For instance, if a post is not found, we can just toss a NotFoundException, and the application will handle it accordingly, but, not by showing a 500 error as usual, instead we’re going to setup custom error handlers. You could alternatively use <code>App::abort(404)</code> or something along those lines, but I find that this method saves me many conditional statements and repeat code, as well as allowing me to adjust the implementation of error reporting in a single place very easily.</p>
    <p>First let's define the custom Exceptions. Create a file in your <code>app</code> folder called <code>errors.php</code></p>
    <pre>touch app/errors.php&#x000A;    </pre>
    <p><strong>app/errors.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    class PermissionException extends Exception {&#x000A;    &#x000A;      public function __construct($message = null, $code = 403)&#x000A;      {&#x000A;        parent::__construct($message ?: 'Action not allowed', $code);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class ValidationException extends Exception {&#x000A;    &#x000A;      protected $messages;&#x000A;    &#x000A;      /**&#x000A;       * We are adjusting this constructor to receive an instance&#x000A;       * of the validator as opposed to a string to save us some typing&#x000A;       * @param Validator $validator failed validator object&#x000A;       */&#x000A;      public function __construct($validator)&#x000A;      {&#x000A;        $this-&gt;messages = $validator-&gt;messages();&#x000A;        parent::__construct($this-&gt;messages, 400);&#x000A;      }&#x000A;    &#x000A;      public function getMessages()&#x000A;      {&#x000A;        return $this-&gt;messages;&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class NotFoundException extends Exception {&#x000A;    &#x000A;      public function __construct($message = null, $code = 404)&#x000A;      {&#x000A;        parent::__construct($message ?: 'Resource Not Found', $code);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p>These are very simple Exceptions, notice for the ValidationException, we can just pass it the failed validator instance and it will handle the error messages accordingly!</p>
    <p>Now we need to define our error handlers that will be called when one of these Exceptions are thrown. These are basically Event listeners, whenever one of these exceptions are thrown, it’s treated as an Event and calls the appropriate function. It’s very simple to add logging or any other error handling procedures here.</p>
    <p><strong>app/filters.php</strong></p>
    <pre>...&#x000A;    &#x000A;    /**&#x000A;     * General HttpException handler&#x000A;     */&#x000A;    App::error( function(Symfony\Component\HttpKernel\Exception\HttpException $e, $code)&#x000A;    {&#x000A;      $headers = $e-&gt;getHeaders();&#x000A;    &#x000A;      switch($code)&#x000A;      {&#x000A;        case 401:&#x000A;          $default_message = 'Invalid API key';&#x000A;          $headers['WWW-Authenticate'] = 'Basic realm="CRM REST API"';&#x000A;        break;&#x000A;    &#x000A;        case 403:&#x000A;          $default_message = 'Insufficient privileges to perform this action';&#x000A;        break;&#x000A;    &#x000A;        case 404:&#x000A;          $default_message = 'The requested resource was not found';&#x000A;        break;&#x000A;    &#x000A;        default:&#x000A;          $default_message = 'An error was encountered';&#x000A;      }&#x000A;    &#x000A;      return Response::json(array(&#x000A;        'error' =&gt; $e-&gt;getMessage() ?: $default_message&#x000A;      ), $code, $headers);&#x000A;    });&#x000A;    &#x000A;    /**&#x000A;     * Permission Exception Handler&#x000A;     */&#x000A;    App::error(function(PermissionException $e, $code)&#x000A;    {&#x000A;      return Response::json($e-&gt;getMessage(), $e-&gt;getCode());&#x000A;    });&#x000A;    &#x000A;    /**&#x000A;     * Validation Exception Handler&#x000A;     */&#x000A;    App::error(function(ValidationException $e, $code)&#x000A;    {&#x000A;      return Response::json($e-&gt;getMessages(), $code);&#x000A;    });&#x000A;    &#x000A;    /**&#x000A;     * Not Found Exception Handler&#x000A;     */&#x000A;    App::error(function(NotFoundException $e)&#x000A;    {&#x000A;      return Response::json($e-&gt;getMessage(), $e-&gt;getCode());&#x000A;    });&#x000A;    </pre>
    <p>We now need to let our auto-loader know about these new files. So we must tell Composer where to check for them:</p>
    <p><strong>composer.json</strong></p>
    <p>Notice that we added the <code>"app/errors.php"</code> line.</p>
    <pre>{&#x000A;      "require": {&#x000A;        "laravel/framework": "4.0.*",&#x000A;        "way/generators": "dev-master",&#x000A;        "twitter/bootstrap": "dev-master",&#x000A;        "conarwelsh/mustache-l4": "dev-master"&#x000A;      },&#x000A;      "require-dev": {&#x000A;        "phpunit/phpunit": "3.7.*",&#x000A;        "mockery/mockery": "0.7.*"&#x000A;      },&#x000A;      "autoload": {&#x000A;        "classmap": [&#x000A;          "app/commands",&#x000A;          "app/controllers",&#x000A;          "app/models",&#x000A;          "app/database/migrations",&#x000A;          "app/database/seeds",&#x000A;          "app/tests/TestCase.php",&#x000A;          "app/repositories",&#x000A;          "app/errors.php"&#x000A;        ]&#x000A;      },&#x000A;      "scripts": {&#x000A;        "post-update-cmd": "php artisan optimize"&#x000A;      },&#x000A;      "minimum-stability": "dev"&#x000A;    }&#x000A;    </pre>
    <p>We must now tell Composer to actually check for these files and include them in the auto-load registry.</p>
    <pre>composer dump-autoload&#x000A;    </pre>
    <p>Great, so we have completed our controllers and our repositories, the last two items in our MVRC that we have to take care of is the models and views, both of which are pretty straight forward.</p>
    <p><strong>app/models/Post.php</strong></p>
    <pre>&lt;?php&#x000A;    /**&#x000A;     * Represent a Post Item, or Collection&#x000A;     */&#x000A;    class Post extends Eloquent {&#x000A;    &#x000A;      /**&#x000A;       * Items that are "fillable"&#x000A;       * meaning we can mass-assign them from the constructor&#x000A;       * or $post-&gt;fill()&#x000A;       * @var array&#x000A;       */&#x000A;      protected $fillable = array(&#x000A;        'title', 'content', 'author_name'&#x000A;      );&#x000A;    &#x000A;      /**&#x000A;       * Validation Rules&#x000A;       * this is just a place for us to store these, you could&#x000A;       * alternatively place them in your repository&#x000A;       * @var array&#x000A;       */&#x000A;      public static $rules = array(&#x000A;        'title'    =&gt; 'required',&#x000A;        'author_name' =&gt; 'required'&#x000A;      );&#x000A;    &#x000A;      /**&#x000A;       * Define the relationship with the comments table&#x000A;       * @return Collection collection of Comment Models&#x000A;       */&#x000A;      public function comments()&#x000A;      {&#x000A;        return $this-&gt;hasMany('Comment');&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p><strong>app/models/Comment.php</strong></p>
    <pre>&lt;?php&#x000A;    /**&#x000A;     * Represent a Comment Item, or Collection&#x000A;     */&#x000A;    class Comment extends Eloquent {&#x000A;    &#x000A;      /**&#x000A;       * Items that are "fillable"&#x000A;       * meaning we can mass-assign them from the constructor&#x000A;       * or $comment-&gt;fill()&#x000A;       * @var array&#x000A;       */&#x000A;      protected $fillable = array(&#x000A;        'post_id', 'content', 'author_name'&#x000A;      );&#x000A;    &#x000A;      /**&#x000A;       * Validation Rules&#x000A;       * this is just a place for us to store these, you could&#x000A;       * alternatively place them in your repository&#x000A;       * @var array&#x000A;       */&#x000A;      public static $rules = array(&#x000A;        'post_id'   =&gt; 'required|numeric',&#x000A;        'content'   =&gt; 'required',&#x000A;        'author_name' =&gt; 'required'&#x000A;      );&#x000A;    &#x000A;      /**&#x000A;       * Define the relationship with the posts table&#x000A;       * @return Model parent Post model&#x000A;       */&#x000A;      public function post()&#x000A;      {&#x000A;        return $this-&gt;belongsTo('Post');&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p>As far as views are concerned, I’m just going to mark up some simple bootstrap-friendly pages. Remember to change each files extension to <code>.mustache</code> though, since our generator thought that we would be using <code>.blade.php</code>. We’re also going to create a few "partial" views using the Rails convention of prefixing them with an <code>_</code> to signify a partial.</p>
    <blockquote><p>Note: I skipped a few views, as we will not be using them in this tutorial.</p></blockquote>
    <p><strong>public/views/posts/index.mustache</strong></p>
    <p>For the <code>index</code> page view we’ll just loop over all of our posts, showing the post partial for each.</p>
    <pre>{{#posts}}&#x000A;      {{&gt; posts._post}}&#x000A;    {{/posts}}&#x000A;    </pre>
    <p><strong>public/views/posts/show.mustache</strong></p>
    <p>For the <code>show</code> view we’ll show an entire post and its comments:</p>
    <pre>&lt;article&gt;&#x000A;      &lt;h3&gt;&#x000A;        {{ post.title }} {{ post.id }}&#x000A;        &lt;small&gt;{{ post.author_name }}&lt;/small&gt;&#x000A;      &lt;/h3&gt;&#x000A;      &lt;div&gt;&#x000A;        {{ post.content }}&#x000A;      &lt;/div&gt;&#x000A;    &lt;/article&gt;&#x000A;    &#x000A;    &lt;div&gt;&#x000A;      &lt;h2&gt;Add A Comment&lt;/h2&gt;&#x000A;      {{&gt; comments._form }}&#x000A;    &#x000A;      &lt;section data-role="comments"&gt;&#x000A;        {{#post.comments}}&#x000A;          &lt;div&gt;&#x000A;            {{&gt; comments._comment }}&#x000A;          &lt;/div&gt;&#x000A;        {{/post.comments}}&#x000A;      &lt;/section&gt;&#x000A;    &lt;/div&gt;&#x000A;    </pre>
    <p><strong>public/views/posts/_post.mustache</strong></p>
    <p>Here’s the partial that we’ll use to show a <code>post</code> in a list. This is used on our <code>index</code> view.</p>
    <pre>&lt;article data-toggle="view" data-target="posts/{{ id }}"&gt;&#x000A;      &lt;h3&gt;{{ title }} {{ id }}&lt;/h3&gt;&#x000A;      &lt;cite&gt;{{ author_name }} on {{ created_at }}&lt;/cite&gt;&#x000A;    &lt;/article&gt;&#x000A;    </pre>
    <p><strong>public/views/posts/_form.mustache</strong></p>
    <p>Here’s the <code>form</code> partial needed to create a post, we’ll use this from our API, but this could also be a useful view in an admin panel and other places, which is why we choose to make it a partial.</p>
    <pre>{{#exists}}&#x000A;      &lt;form action="/v1/posts/{{ post.id }}" method="post"&gt;&#x000A;        &lt;input type="hidden" name="_method" value="PUT" /&gt;&#x000A;    {{/exists}}&#x000A;    {{^exists}}&#x000A;      &lt;form action="/v1/posts" method="post"&gt;&#x000A;    {{/exists}}&#x000A;    &#x000A;      &lt;fieldset&gt;&#x000A;    &#x000A;        &lt;div class="control-group"&gt;&#x000A;          &lt;label class="control-label"&gt;&lt;/label&gt;&#x000A;          &lt;div class="controls"&gt;&#x000A;            &lt;input type="text" name="title" value="{{ post.title }}" /&gt;&#x000A;          &lt;/div&gt;&#x000A;        &lt;/div&gt;&#x000A;    &#x000A;        &lt;div class="control-group"&gt;&#x000A;          &lt;label class="control-label"&gt;&lt;/label&gt;&#x000A;          &lt;div class="controls"&gt;&#x000A;            &lt;input type="text" name="author_name" value="{{ post.author_name }}" /&gt;&#x000A;          &lt;/div&gt;&#x000A;        &lt;/div&gt;&#x000A;    &#x000A;        &lt;div class="control-group"&gt;&#x000A;          &lt;label class="control-label"&gt;&lt;/label&gt;&#x000A;          &lt;div class="controls"&gt;&#x000A;            &lt;textarea name="content"&gt;{{ post.content }}"&lt;/textarea&gt;&#x000A;          &lt;/div&gt;&#x000A;        &lt;/div&gt;&#x000A;    &#x000A;        &lt;div class="form-actions"&gt;&#x000A;          &lt;input type="submit" class="btn btn-primary" value="Save" /&gt;&#x000A;        &lt;/div&gt;&#x000A;    &#x000A;      &lt;/fieldset&gt;&#x000A;    &lt;/form&gt;&#x000A;    </pre>
    <p><strong>public/views/comments/_comment.mustache</strong></p>
    <p>Here’s the <code>comment</code> partial which is used to represent a single comment in a list of comments:</p>
    <pre>&lt;h5&gt;&#x000A;      {{ author_name }}&#x000A;      &lt;small&gt;{{ created_at }}&lt;/small&gt;&#x000A;    &lt;/h5&gt;&#x000A;    &lt;div&gt;&#x000A;      {{ content }}&#x000A;    &lt;/div&gt;&#x000A;    </pre>
    <p><strong>public/views/comments/_form.mustache</strong></p>
    <p>The form needed to create a comment – both used in the API and the Show Post view:</p>
    <pre>{{#exists}}&#x000A;      &lt;form class="form-horizontal" action="/v1/posts/{{ comment.post_id }}/{{ id }}" method="post"&gt;&#x000A;        &lt;input type="hidden" name="_method" value="PUT" /&gt;&#x000A;    {{/exists}}&#x000A;    {{^exists}}&#x000A;      &lt;form class="form-horizontal" action="/v1/posts/{{ comment.post_id }}" method="post"&gt;&#x000A;    {{/exists}}&#x000A;    &#x000A;      &lt;fieldset&gt;&#x000A;    &#x000A;        &lt;div class="control-group"&gt;&#x000A;          &lt;label class="control-label"&gt;Author Name&lt;/label&gt;&#x000A;          &lt;div class="controls"&gt;&#x000A;            &lt;input type="text" name="author_name" value="{{ comment.author_name }}" /&gt;&#x000A;          &lt;/div&gt;&#x000A;        &lt;/div&gt;&#x000A;    &#x000A;        &lt;div class="control-group"&gt;&#x000A;          &lt;label class="control-label"&gt;Comment&lt;/label&gt;&#x000A;          &lt;div class="controls"&gt;&#x000A;            &lt;textarea name="content"&gt;{{ comment.content }}&lt;/textarea&gt;&#x000A;          &lt;/div&gt;&#x000A;        &lt;/div&gt;&#x000A;    &#x000A;        &lt;div class="form-actions"&gt;&#x000A;          &lt;input type="submit" class="btn btn-primary" value="Save" /&gt;&#x000A;        &lt;/div&gt;&#x000A;    &#x000A;      &lt;/fieldset&gt;&#x000A;    &lt;/form&gt;&#x000A;    </pre>
    <p><strong>public/views/layouts/_notification.mustache</strong></p>
    <p>And here’s the helper view partial to allow us to show a notification:</p>
    <pre>&lt;div class="alert alert-{{type}}"&gt;&#x000A;      {{message}}&#x000A;    &lt;/div&gt;&#x000A;    </pre>
    <p>Great, we have all of our API components in place. Let's run our unit tests to see where we’re at!</p>
    <pre>vendor/phpunit/phpunit/phpunit.php&#x000A;    </pre>
    <p>Your first run of this test should pass with flying (green) colors. However, if you were to run this test again, you’ll notice that it fails now with a handful of errors, and that is because our repository tests actually tested the database, and in doing so deleted some of the records our previous tests used to assert values. This is an easy fix, all we have to do is tell our tests that they need to re-seed the database after each test. In addition, we did not receive a noticable error for this, but we did not close Mockery after each test either, this is a requirement of Mockery that you can find in their docs. So let's add both missing methods.</p>
    <p>Open up <code>app/tests/TestCase.php</code> and add the following two methods:</p>
    <pre>/**&#x000A;     * setUp is called prior to each test&#x000A;     */&#x000A;    public function setUp()&#x000A;    {&#x000A;      parent::setUp();&#x000A;      $this-&gt;seed();&#x000A;    }&#x000A;    &#x000A;    /**&#x000A;     * tearDown is called after each test&#x000A;     * @return [type] [description]&#x000A;     */&#x000A;    public function tearDown()&#x000A;    {&#x000A;      Mockery::close();&#x000A;    }&#x000A;    </pre>
    <p>This is great, we now said that at every "setUp", which is run before each test, to re-seed the database. However we still have one problem, everytime you re-seed, it’s only going to append new rows to the tables. Our tests are looking for items with a row ID of one, so we still have a few changes to make. We just need to tell the database to truncate our tables when seeding:</p>
    <p><strong>app/database/seeds/CommentsTableSeeder.php</strong></p>
    <p>Before we insert the new rows, we’ll truncate the table, deleting all rows and resetting the auto-increment counter.</p>
    <pre>&lt;?php&#x000A;    &#x000A;    class CommentsTableSeeder extends Seeder {&#x000A;    &#x000A;      public function run()&#x000A;      {&#x000A;        $comments = array(&#x000A;          array(&#x000A;            'content'   =&gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',&#x000A;            'author_name' =&gt; 'Testy McTesterson',&#x000A;            'post_id'   =&gt; 1,&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;          array(&#x000A;            'content'   =&gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',&#x000A;            'author_name' =&gt; 'Testy McTesterson',&#x000A;            'post_id'   =&gt; 1,&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;          array(&#x000A;            'content'   =&gt; 'Lorem ipsum Nisi dolore ut incididunt mollit tempor proident eu velit cillum dolore sed',&#x000A;            'author_name' =&gt; 'Testy McTesterson',&#x000A;            'post_id'   =&gt; 2,&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;        );&#x000A;    &#x000A;        //truncate the comments table when we seed&#x000A;        DB::table('comments')-&gt;truncate();&#x000A;        DB::table('comments')-&gt;insert($comments);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p><strong>app/database/seeds/PostsTableSeeder.php</strong></p>
    <pre>&lt;?php&#x000A;    &#x000A;    class PostsTableSeeder extends Seeder {&#x000A;    &#x000A;      public function run()&#x000A;      {&#x000A;        $posts = array(&#x000A;          array(&#x000A;            'title'    =&gt; 'Test Post',&#x000A;            'content'   =&gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',&#x000A;            'author_name' =&gt; 'Conar Welsh',&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          ),&#x000A;          array(&#x000A;            'title'    =&gt; 'Another Test Post',&#x000A;            'content'   =&gt; 'Lorem ipsum Reprehenderit velit est irure in enim in magna aute occaecat qui velit ad.',&#x000A;            'author_name' =&gt; 'Conar Welsh',&#x000A;            'created_at' =&gt; date('Y-m-d H:i:s'),&#x000A;            'updated_at' =&gt; date('Y-m-d H:i:s'),&#x000A;          )&#x000A;        );&#x000A;    &#x000A;        //truncate the posts table each time we seed&#x000A;        DB::table('posts')-&gt;truncate();&#x000A;        DB::table('posts')-&gt;insert($posts);&#x000A;      }&#x000A;    &#x000A;    }&#x000A;    </pre>
    <p>Now you should be able to run the tests any number of times and get passing tests each time! That means we have fulfilled our TDD cycle and we’re not allowed to write anymore production code for our API!! Let's just commit our changes to our repo and move onto the Backbone application!</p>
    <pre>git add . &amp;&amp; git commit -am "built out the API and corresponding tests"&#x000A;    </pre>
    <hr>
    <h2>Backbone App</h2>
    <p>Now that we have completed all of the back-end work, we can move forward to creating a nice user interface to access all of that data. We’ll keep this part of the project a little bit on the simpler side, and I warn you that my approach can be considered an opinionated one. I have seen many people with so many different methods for structuring a Backbone application. My trials and errors have led me to my current method, if you do not agree with it, my hope is that it may inspire you to find your own!</p>
    <p>We’re going to use the Mustache templating engine instead of Underscore, this will allow us to share our views between the client and server! The trick is in how you load the views, we’re going to use AJAX in this tutorial, but it’s just as easy to load them all into the main template, or precompile them.</p>
    <h3>Router</h3>
    <p>First we’ll get our router going. There are two parts to this, the Laravel router, and the Backbone router.</p>
    <h4>Laravel Router</h4>
    <p>There are two main approaches we can take here:</p>
    <h5>Approach #1: The catch-all</h5>
    <p>Remember I told you when you were adding the resource routes that it was important that you placed them ABOVE the app route?? The catch-all method is the reason for that statement. The overall goal of this method is to have any routes that have not found a match in Laravel, be caught and sent to Backbone. Implementing this method is easy:</p>
    <p><strong>app/routes.php</strong></p>
    <pre>// change your existing app route to this:&#x000A;    // we are basically just giving it an optional parameter of "anything"&#x000A;    Route::get('/{path?}', function($path = null)&#x000A;    {&#x000A;      return View::make('app');&#x000A;    })&#x000A;    -&gt;where('path', '.*'); //regex to match anything (dots, slashes, letters, numbers, etc)&#x000A;    </pre>
    <p>Now, every route other than our API routes will render our app view.</p>
    <p>In addition, if you have a multi-page app (several single page apps), you can define several of these catch-alls:</p>
    <pre>Route::get('someApp1{path?}', function($path = null)&#x000A;    {&#x000A;      return View::make('app');&#x000A;    })&#x000A;    -&gt;where('path', '.*');&#x000A;    &#x000A;    Route::get('anotherApp/{path?}', function($path = null)&#x000A;    {&#x000A;      return View::make('app');&#x000A;    })&#x000A;    -&gt;where('path', '.*');&#x000A;    &#x000A;    Route::get('athirdapp{path?}', function($path = null)&#x000A;    {&#x000A;      return View::make('app');&#x000A;    })&#x000A;    -&gt;where('path', '.*');&#x000A;    </pre>
    <blockquote><p>Note: Keep in mind the '/' before {path?}. If that slash is there, it’ll be required in the URL (with the exception of the index route), sometimes this is desired and sometimes not.</p></blockquote>
    <h5>Approach #2:</h5>
    <p>Since our front and back end share views… wouldn't it be extremely easy to just define routes in both places? You can even do this <em>in addition</em> to the catch-all approach if you want.</p>
    <p>The routes that we’re going to end up defining for the app are simply:</p>
    <pre>GET /&#x000A;    GET /posts/:id&#x000A;    </pre>
    <p>app/routes.php</p>
    <pre>&lt;?php&#x000A;    &#x000A;    App::bind('PostRepositoryInterface', 'EloquentPostRepository'); &#x000A;    App::bind('CommentRepositoryInterface', 'EloquentCommentRepository');&#x000A;    //create a group of routes that will belong to APIv1&#x000A;    Route::group(array('prefix' =&gt; 'v1'), function()&#x000A;    {&#x000A;      Route::resource('posts', 'V1\PostsController');&#x000A;      Route::resource('posts.comments', 'V1\PostsCommentsController');&#x000A;    });&#x000A;    /**&#x000A;     * Method #1: use catch-all&#x000A;     * optionally commented out while we use Method 2&#x000A;     */&#x000A;    // change your existing app route to this:&#x000A;    // we are basically just giving it an optional parameter of "anything"&#x000A;    // Route::get('/{path?}', function($path = null)&#x000A;    // {&#x000A;    //   return View::make('layouts.application')-&gt;nest('content', 'app');&#x000A;    // })&#x000A;    // -&gt;where('path', '.*'); //regex to match anything (dots, slashes, letters, numbers, etc)&#x000A;    /**&#x000A;     * Method #2: define each route&#x000A;     */&#x000A;    Route::get('/', function()&#x000A;    {&#x000A;      $posts = App::make('PostRepositoryInterface')-&gt;paginate();&#x000A;      return View::make('layouts.application')-&gt;nest('content', 'posts.index', array(&#x000A;        'posts' =&gt; $posts&#x000A;      ));&#x000A;    });&#x000A;    &#x000A;    Route::get('posts/{id}', function($id)&#x000A;    {&#x000A;      $post = App::make('PostRepositoryInterface')-&gt;findById($id);&#x000A;      return View::make('layouts.application')-&gt;nest('content', 'posts.show', array(&#x000A;        'post' =&gt; $post&#x000A;      ));&#x000A;    });&#x000A;    </pre>
    <p>Pretty cool huh?! Regardless of which method we use, or the combination of both, your Backbone router will end up mostly the same.</p>
    <p>Notice that we’re using our Repository again, this is yet another reason why Repositories are a useful addition to our framework. We can now run almost all of the logic that the controller does, but without repeating hardly any of the code!</p>
    <p>Keep in mind a few things while choosing which method to use, if you use the catch-all, it will do just like the name implies… catch-<em>ALL</em>. This means there is no such thing as a 404 on your site anymore. No matter the request, its landing on the app page (unless you manually toss an exception somewhere such as your repository). The inverse is, with defining each route, now you have two sets of routes to manage. Both methods have their ups and downs, but both are equally easy to deal with.</p>
    <h3>Base View</h3>
    <p>One view to rule them all! This <code>BaseView</code> is the view that all of our other Views will inherit from. For our purposes, this view has but one job… templating! In a larger app this view is a good place to put other shared logic.</p>
    <p>We’ll simply extend <code>Backbone.View</code> and add a <code>template</code> function that will return our view from the cache if it exists, or get it via AJAX and place it in the cache. We have to use synchronous AJAX due to the way that Mustache.js fetches partials, but since we’re only retrieving these views if they are not cached, we shouldn’t receive much of a performance hit here.</p>
    <pre>/**&#x000A;     ***************************************&#x000A;     * Array Storage Driver&#x000A;     * used to store our views&#x000A;     ***************************************&#x000A;     */&#x000A;    var ArrayStorage = function(){&#x000A;      this.storage = {};&#x000A;    };&#x000A;    ArrayStorage.prototype.get = function(key)&#x000A;    {&#x000A;      return this.storage[key];&#x000A;    };&#x000A;    ArrayStorage.prototype.set = function(key, val)&#x000A;    {&#x000A;      return this.storage[key] = val;&#x000A;    };&#x000A;    /**&#x000A;     ***************************************&#x000A;     * Base View&#x000A;     ***************************************&#x000A;     */&#x000A;    var BaseView = bb.View.extend({&#x000A;    &#x000A;      /**&#x000A;       * Set our storage driver&#x000A;       */&#x000A;      templateDriver: new ArrayStorage,&#x000A;    &#x000A;      /**&#x000A;       * Set the base path for where our views are located&#x000A;       */&#x000A;      viewPath: '/views/',&#x000A;    &#x000A;      /**&#x000A;       * Get the template, and apply the variables&#x000A;       */&#x000A;      template: function()&#x000A;      {&#x000A;        var view, data, template, self;&#x000A;    &#x000A;        switch(arguments.length)&#x000A;        {&#x000A;          case 1:&#x000A;            view = this.view;&#x000A;            data = arguments[0];&#x000A;            break;&#x000A;          case 2:&#x000A;            view = arguments[0];&#x000A;            data = arguments[1];&#x000A;            break;&#x000A;        }&#x000A;    &#x000A;        template = this.getTemplate(view, false);&#x000A;        self = this;&#x000A;    &#x000A;        return template(data, function(partial)&#x000A;        {&#x000A;          return self.getTemplate(partial, true);&#x000A;        });&#x000A;      },&#x000A;    &#x000A;      /**&#x000A;       * Facade that will help us abstract our storage engine,&#x000A;       * should we ever want to swap to something like LocalStorage&#x000A;       */&#x000A;      getTemplate: function(view, isPartial)&#x000A;      {&#x000A;        return this.templateDriver.get(view) || this.fetch(view, isPartial);&#x000A;      },&#x000A;    &#x000A;      /**&#x000A;       * Facade that will help us abstract our storage engine,&#x000A;       * should we ever want to swap to something like LocalStorage&#x000A;       */&#x000A;      setTemplate: function(name, template)&#x000A;      {&#x000A;        return this.templateDriver.set(name, template);&#x000A;      },&#x000A;    &#x000A;      /**&#x000A;       * Function to retrieve the template via ajax&#x000A;       */&#x000A;      fetch: function(view, isPartial)&#x000A;      {&#x000A;        var markup = $.ajax({&#x000A;          async: false,&#x000A;    &#x000A;          //the URL of our template, we can optionally use dot notation&#x000A;          url: this.viewPath + view.split('.').join('/') + '.mustache'&#x000A;        }).responseText;&#x000A;    &#x000A;        return isPartial&#x000A;          ? markup&#x000A;          : this.setTemplate(view, Mustache.compile(markup));&#x000A;      }&#x000A;    });&#x000A;    </pre>
    <h3>PostView</h3>
    <p>The <code>PostView</code> renders a single blog post:</p>
    <pre>// this view will show an entire post&#x000A;    // comment form, and comments&#x000A;    var PostView = BaseView.extend({&#x000A;    &#x000A;      //the location of the template this view will use, we can use dot notation&#x000A;      view: 'posts.show',&#x000A;    &#x000A;      //events this view should subscribe to&#x000A;      events: {&#x000A;        'submit form': function(e)&#x000A;        {&#x000A;          e.preventDefault();&#x000A;          e.stopPropagation();&#x000A;    &#x000A;          return this.addComment( $(e.target).serialize() );&#x000A;        }&#x000A;      },&#x000A;    &#x000A;      //render our view into the defined `el`&#x000A;      render: function()&#x000A;      {&#x000A;        var self = this;&#x000A;    &#x000A;        self.$el.html( this.template({&#x000A;          post: this.model.attributes&#x000A;        }) );&#x000A;      },&#x000A;    &#x000A;      //add a comment for this post&#x000A;      addComment: function(formData)&#x000A;      {&#x000A;        var&#x000A;          self = this,&#x000A;    &#x000A;          //build our url&#x000A;          action = this.model.url() + '/comments'&#x000A;        ;&#x000A;    &#x000A;        //submit a post to our api&#x000A;        $.post(action, formData, function(comment, status, xhr)&#x000A;        {&#x000A;          //create a new comment partial&#x000A;          var view = new CommentViewPartial({&#x000A;            //we are using a blank backbone model, since we done have any specific logic needed&#x000A;            model: new bb.Model(comment)&#x000A;          });&#x000A;    &#x000A;          //prepend the comment partial to the comments list&#x000A;          view.render().$el.prependTo(self.$('[data-role="comments"]'));&#x000A;    &#x000A;          //reset the form&#x000A;          self.$('input[type="text"], textarea').val('');&#x000A;    &#x000A;          //prepend our new comment to the collection&#x000A;          self.model.attributes.comments.unshift(comment);&#x000A;    &#x000A;          //send a notification that we successfully added the comment&#x000A;          notifications.add({&#x000A;            type: 'success',&#x000A;            message: 'Comment Added!'&#x000A;          });&#x000A;        });&#x000A;    &#x000A;      }&#x000A;    });&#x000A;    </pre>
    <h3>Partial Views</h3>
    <p>We’ll need a few views to render partials. We mainly just need to tell the view which template to use and that it should extend our view that provides the method to fetch our template.</p>
    <pre>// this will be used for rendering a single comment in a list&#x000A;    var CommentViewPartial = BaseView.extend({&#x000A;      //define our template location&#x000A;      view: 'comments._comment',&#x000A;      render: function()&#x000A;      {&#x000A;        this.$el.html( this.template(this.model.attributes) );&#x000A;        return this;&#x000A;      }&#x000A;    });&#x000A;    &#x000A;    //this view will be used for rendering a single post in a list&#x000A;    var PostViewPartial = BaseView.extend({&#x000A;      //define our template location&#x000A;      view: 'posts._post',&#x000A;      render: function()&#x000A;      {&#x000A;        this.$el.html( this.template(this.model.attributes) );&#x000A;        return this;&#x000A;      }&#x000A;    });&#x000A;    </pre>
    <h3>Blog View</h3>
    <p>This is our overall application view. It contains our configuration logic, as well as handling the fetching of our <code>PostCollection</code>. We also setup a cool little infinite scroll feature. Notice how we’re using jQuery promises to ensure that the fetching of our collection has completed prior to rendering the view.</p>
    <pre>var Blog = BaseView.extend({&#x000A;      //define our template location&#x000A;      view: 'posts.index',&#x000A;    &#x000A;      //setup our app configuration&#x000A;      initialize: function()&#x000A;      {&#x000A;        this.perPage = this.options.perPage || 15;&#x000A;        this.page   = this.options.page || 0;&#x000A;        this.fetching = this.collection.fetch();&#x000A;    &#x000A;        if(this.options.infiniteScroll) this.enableInfiniteScroll();&#x000A;      },&#x000A;    &#x000A;      //wait til the collection has been fetched, and render the view&#x000A;      render: function()&#x000A;      {&#x000A;        var self = this;&#x000A;        this.fetching.done(function()&#x000A;        {&#x000A;          self.$el.html('');&#x000A;          self.addPosts();&#x000A;    &#x000A;          // var posts = this.paginate()&#x000A;    &#x000A;          // for(var i=0; i&lt;posts.length; i++)&#x000A;          // {&#x000A;          //   posts[i] = posts[i].toJSON();&#x000A;          // }&#x000A;    &#x000A;          // self.$el.html( self.template({&#x000A;          //   posts: posts&#x000A;          // }) );&#x000A;    &#x000A;          if(self.options.infiniteScroll) self.enableInfiniteScroll();&#x000A;        });&#x000A;      },&#x000A;    &#x000A;      //helper function to limit the amount of posts we show at a time&#x000A;      paginate: function()&#x000A;      {&#x000A;        var posts;&#x000A;        posts = this.collection.rest(this.perPage * this.page);&#x000A;        posts = _.first(posts, this.perPage);&#x000A;        this.page++;&#x000A;    &#x000A;        return posts;&#x000A;      },&#x000A;    &#x000A;      //add the next set of posts to the view&#x000A;      addPosts: function()&#x000A;      {&#x000A;        var posts = this.paginate();&#x000A;    &#x000A;        for(var i=0; i&lt;posts.length; i++)&#x000A;        {&#x000A;          this.addOnePost( posts[i] );&#x000A;        }&#x000A;      },&#x000A;    &#x000A;      //helper function to add a single post to the view&#x000A;      addOnePost: function(model)&#x000A;      {&#x000A;        var view = new PostViewPartial({&#x000A;          model: model&#x000A;        });&#x000A;        this.$el.append( view.render().el );&#x000A;      },&#x000A;    &#x000A;      //this function will show an entire post, we could alternatively make this its own View&#x000A;      //however I personally like having it available in the overall application view, as it&#x000A;      //makes it easier to manage the state&#x000A;      showPost: function(id)&#x000A;      {&#x000A;        var self = this;&#x000A;    &#x000A;        this.disableInifiniteScroll();&#x000A;    &#x000A;        this.fetching.done(function()&#x000A;        {&#x000A;          var model = self.collection.get(id);&#x000A;    &#x000A;          if(!self.postView)&#x000A;          {&#x000A;            self.postView = new self.options.postView({&#x000A;              el: self.el&#x000A;            });&#x000A;          }&#x000A;          self.postView.model = model;&#x000A;          self.postView.render();&#x000A;        });&#x000A;      },&#x000A;    &#x000A;      //function to run during the onScroll event&#x000A;      infiniteScroll: function()&#x000A;      {&#x000A;        if($window.scrollTop() &gt;= $document.height() - $window.height() - 50)&#x000A;        {&#x000A;          this.addPosts();&#x000A;        }&#x000A;      },&#x000A;    &#x000A;      //listen for the onScoll event&#x000A;      enableInfiniteScroll: function()&#x000A;      {&#x000A;        var self = this;&#x000A;    &#x000A;        $window.on('scroll', function()&#x000A;        {&#x000A;          self.infiniteScroll();&#x000A;        });&#x000A;      },&#x000A;    &#x000A;      //stop listening to the onScroll event&#x000A;      disableInifiniteScroll: function()&#x000A;      {&#x000A;        $window.off('scroll');&#x000A;      }&#x000A;    });&#x000A;    </pre>
    <h3>PostCollection</h3>
    <p>Setup our <code>PostCollection</code> – we just need to tell the Collection the URL it should use to fetch its contents.</p>
    <pre>// the posts collection is configured to fetch&#x000A;    // from our API, as well as use our PostModel&#x000A;    var PostCollection = bb.Collection.extend({&#x000A;      url: '/v1/posts'&#x000A;    });&#x000A;    </pre>
    <h3>Blog Router</h3>
    <p>Notice that we’re not instantiating new instances of our views, we’re merely telling them to render. Our initialize functions are designed to only be ran once, as we don’t want them to run but once, on page load.</p>
    <pre>var BlogRouter = bb.Router.extend({&#x000A;      routes: {&#x000A;        "": "index",&#x000A;        "posts/:id": "show"&#x000A;      },&#x000A;      initialize: function(options)&#x000A;      {&#x000A;        // i do this to avoid having to hardcode an instance of a view&#x000A;        // when we instantiate the router we will pass in the view instance&#x000A;        this.blog = options.blog;&#x000A;      },&#x000A;      index: function()&#x000A;      {&#x000A;        //reset the paginator&#x000A;        this.blog.page = 0;&#x000A;    &#x000A;        //render the post list&#x000A;        this.blog.render();&#x000A;      },&#x000A;      show: function(id)&#x000A;      {&#x000A;        //render the full-post view&#x000A;        this.blog.showPost(id);&#x000A;      }&#x000A;    });&#x000A;    </pre>
    <h3>Notifications Collection</h3>
    <p>We’re just going to setup a simple Collection to store user notifications:</p>
    <pre>var notifications = new bb.Collection();&#x000A;    </pre>
    <h3>NotificationsView</h3>
    <p>This view will handle the displaying and hiding of user notifications:</p>
    <pre>var NotificationView = BaseView.extend({&#x000A;      el: $('#notifications'),&#x000A;      view: 'layouts._notification',&#x000A;      initialize: function()&#x000A;      {&#x000A;        this.listenTo(notifications, 'add', this.render);&#x000A;      },&#x000A;      render: function(notification)&#x000A;      {&#x000A;        var $message = $( this.template(notification.toJSON()) );&#x000A;        this.$el.append($message);&#x000A;        this.delayedHide($message);&#x000A;      },&#x000A;      delayedHide: function($message)&#x000A;      {&#x000A;        var timeout = setTimeout(function()&#x000A;        {&#x000A;          $message.fadeOut(function()&#x000A;          {&#x000A;            $message.remove();&#x000A;          });&#x000A;        }, 5*1000);&#x000A;    &#x000A;        var self = this;&#x000A;        $message.hover(&#x000A;          function()&#x000A;          {&#x000A;            timeout = clearTimeout(timeout);&#x000A;          },&#x000A;          function()&#x000A;          {&#x000A;            self.delayedHide($message);&#x000A;          }&#x000A;        );&#x000A;      }&#x000A;    });&#x000A;    var notificationView = new NotificationView();&#x000A;    </pre>
    <h3>Error Handling</h3>
    <p>Since we used the custom exception handlers for our API, it makes it very easy to handle any error our API may throw. Very similar to the way we defined our event listeners for our API in the <code>app/filters.php</code> file, we’ll define event listeners for our app here. Each code that could be thrown can just show a notification very easily!</p>
    <pre>$.ajaxSetup({&#x000A;      statusCode: {&#x000A;        401: function()&#x000A;        {&#x000A;          notification.add({&#x000A;            type: null, //error, success, info, null&#x000A;            message: 'You do not have permission to do that'&#x000A;          });&#x000A;        },&#x000A;        403: function()&#x000A;        {&#x000A;          notification.add({&#x000A;            type: null, //error, success, info, null&#x000A;            message: 'You do not have permission to do that'&#x000A;          });&#x000A;        },&#x000A;        404: function()&#x000A;        {&#x000A;          notification.add({&#x000A;            type: 'error', //error, success, info, null&#x000A;            message: '404: Page Not Found'&#x000A;          });&#x000A;        },&#x000A;        500: function()&#x000A;        {&#x000A;          notification.add({&#x000A;            type: 'error', //error, success, info, null&#x000A;            message: 'The server encountered an error'&#x000A;          });&#x000A;        }&#x000A;      }&#x000A;    });&#x000A;    </pre>
    <hr>
    <h2>Event Listeners</h2>
    <p>We’ll need a few global event listeners to help us navigate through our app without refreshing the page. We mainly just hijack the default behavior and call <code>Backbone.history.navigate()</code>. Notice how on our first listener, we’re specifying the selector to only match those that don’t have a data attribute of <code>bypass</code>. This will allow us to create links such as <code>&lt;a href="/some/non-ajax/page" data-bypass="true"&gt;link&lt;/a&gt;</code> that will force the page to refresh. We could also go a step further here and check whether the link is a local one, as opposed to a link to another site.</p>
    <pre>$document.on("click", "a[href]:not([data-bypass])", function(e){&#x000A;      e.preventDefault();&#x000A;      e.stopPropagation();&#x000A;    &#x000A;      var href = $(this).attr("href");&#x000A;      bb.history.navigate(href, true);&#x000A;    });&#x000A;    &#x000A;    $document.on("click", "[data-toggle='view']", function(e)&#x000A;    {&#x000A;      e.preventDefault();&#x000A;      e.stopPropagation();&#x000A;    &#x000A;      var&#x000A;        self = $(this),&#x000A;        href = self.attr('data-target') || self.attr('href')&#x000A;      ;&#x000A;    &#x000A;      bb.history.navigate(href, true);&#x000A;    });&#x000A;    </pre>
    <h3>Start The App</h3>
    <p>Now we just need to boot the app, passing in any config values that we need. Notice the line that checks for the <code>silentRouter</code> global variable, this is kind of a hacky way to be able to use both back-end routing methods at the same time. This allows us to define a variable in the view called <code>silentRouter</code> and set it to true, meaning that the router should not actually engage the backbone route, allowing our back-end to handle the initial rendering of the page, and just wait for any needed updates or AJAX.</p>
    <pre>var BlogApp = new Blog({&#x000A;      el       : $('[data-role="main"]'),&#x000A;      collection   : new PostCollection(),&#x000A;      postView    : PostView,&#x000A;      perPage    : 15,&#x000A;      page      : 0,&#x000A;      infiniteScroll : true&#x000A;    });&#x000A;    &#x000A;    var router = new BlogRouter({&#x000A;      blog: BlogApp&#x000A;    });&#x000A;    &#x000A;    if (typeof window.silentRouter === 'undefined') window.silentRouter = true;&#x000A;    &#x000A;    bb.history.start({ pushState: true, root: '/', silent: window.silentRouter });&#x000A;    </pre>
    <hr>
    <h2>Conclusion</h2>
    <p>Notice that for the Backbone portion of our app, all we had to do was write some Javascript that knew how to interact with the pre-existing portions of our application? That’s what I love about this method! It may seem like we had a lot of steps to take to get to that portion of things, but really, most of that work was just a foundation build-up. Once we got that initial foundation in place, the actual application logic falls together very simply.</p>
    <p>Try adding another feature to this blog, such as User listings and info. The basic steps you would take would be something like this:</p>
    <ul>
    <li>Use the generator tool to create a new "User" resource.</li>
    <li>Make the necessary modifications to ensure that the UserController is in the V1 API group.</li>
    <li>Create your Repository and setup the proper IoC bindings in <code>app/routes.php</code>.</li>
    <li>Write your Controller tests one at a time using Mockery for the repository, following each test up with the proper implementation to make sure that test passes.</li>
    <li>Write your Repository tests one at a time, again, following each test up with the implementation.</li>
    <li>Add in the new functionality to your Backbone App. I suggest trying two different approaches to the location of the User views. Decide for yourself which is the better implementation.<ul>
    <li>First place them in their own routes and Main view.</li>
    <li>Then try incorporating them into the overall BlogView.</li>
    </ul>
    </li>
    </ul>
    <p>I hope this gave you some insight into creating a scalable single page app and API using Laravel 4 and Backbone.js. If you have any questions, please ask them in the comment section below!</p>
    </div>
]]>
</Body>
<Summary>For this tutorial, we’re going to be building a single page app using Laravel 4 and Backbone.js. Both frameworks make it very easy to use a different templating engine other than their respective...</Summary>
<Website>http://feedproxy.google.com/~r/nettuts/~3/sp8nPXhAUws/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31309/guest@my.umbc.edu/460439162ee0e35324fb86306a676c82/api/pixel</TrackingUrl>
<Tag>backbone-js</Tag>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>javascript-and-ajax</Tag>
<Tag>laravel</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>wed</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Thu, 13 Jun 2013 21:33:16 -0400</PostedAt>
<EditAt>Thu, 13 Jun 2013 21:33:16 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="123247" important="false" status="posted" url="https://my3.my.umbc.edu/posts/123247">
<Title>Appointment of Professor Tim Nohe as Director of the Center for Innovation, Research, and Creativity in the Arts</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>To: The UMBC Community</p>
    <p>From: John Jeffries, Dean of Arts, Humanities, and Social Sciences</p>
    <p>Date: June 13, 2013</p>
    <p>Re: Appointment of Professor Tim Nohe as Director of the Center for Innovation, Research, and Creativity in the Arts</p>
    <p>I am pleased to announce the appointment of Professor Tim Nohe of the Department of Visual Arts as the founding Director of the new UMBC arts research center—the Center for Innovation, Research, and Creativity in the Arts [CIRCA]. Professor Nohe has achieved a remarkable record at UMBC as a multi-talented and interdisciplinary artist who has exhibited and performed widely, as a fine teacher and mentor, and as a leader in shared governance, most recently as President of the Faculty Senate for two years. His work has included collaborations with all of the arts departments at UMBC and with numerous local, regional, national, and international artists, arts organizations, and universities. He is currently Adjunct Professor at La Trobe University, Melbourne, Australia, and his many distinctions include two Fulbright awards and four Maryland State Arts Council Individual Artist Awards. Professor Nohe will bring his wide-ranging skills, experience, and connections to his new position of Director of CIRCA. I look forward to his working with others, at UMBC and elsewhere, to facilitate innovation, research, and creativity in the arts and to raise the visibility and enhance the already strong reputation of the arts at UMBC.</p>
    </div>
]]>
</Body>
<Summary>To: The UMBC Community   From: John Jeffries, Dean of Arts, Humanities, and Social Sciences   Date: June 13, 2013   Re: Appointment of Professor Tim Nohe as Director of the Center for Innovation,...</Summary>
<Website>https://umbc.edu/stories/appointment-of-professor-tim-nohe-as-director-of-the-center-for-innovation-research-and-creativity-in-the-arts/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/123247/guest@my.umbc.edu/ae768510fa16bd8a80c0823bf8d7310f/api/pixel</TrackingUrl>
<Tag>arts-and-culture</Tag>
<Group token="umbc-news-magazine">UMBC News &amp;amp; Magazine</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/umbc-news-magazine</GroupUrl>
<AvatarUrl>https://assets1-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/xsmall.png?1748556657</AvatarUrl>
<AvatarUrl size="original">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/original.png?1748556657</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/xxlarge.png?1748556657</AvatarUrl>
<AvatarUrl size="xlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/xlarge.png?1748556657</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/large.png?1748556657</AvatarUrl>
<AvatarUrl size="medium">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/medium.png?1748556657</AvatarUrl>
<AvatarUrl size="small">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/small.png?1748556657</AvatarUrl>
<AvatarUrl size="xsmall">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/xsmall.png?1748556657</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/001/943/24435aa6207c452e7bc15cc74b42c7bb/xxsmall.png?1748556657</AvatarUrl>
<Sponsor>UMBC News &amp; Magazine</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>false</CommentsAllowed>
<PostedAt>Thu, 13 Jun 2013 21:05:36 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="31310" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31310">
<Title>Apple Negotiator Defends Tactics in E-Book Trial</Title>
<Body>
<![CDATA[
    <div class="html-content">Eddy Cue, a senior vice president for Apple, denied that the company colluded with publishers to fix e-book prices.<div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fapple-negotiator-defends-tactics-in-e-book-trial.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Negotiator+Defends+Tactics+in+E-Book+Trial" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fapple-negotiator-defends-tactics-in-e-book-trial.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Negotiator+Defends+Tactics+in+E-Book+Trial" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fapple-negotiator-defends-tactics-in-e-book-trial.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Negotiator+Defends+Tactics+in+E-Book+Trial" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fapple-negotiator-defends-tactics-in-e-book-trial.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Negotiator+Defends+Tactics+in+E-Book+Trial" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.nytimes.com%2F2013%2F06%2F14%2Ftechnology%2Fapple-negotiator-defends-tactics-in-e-book-trial.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Negotiator+Defends+Tactics+in+E-Book+Trial" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    </div>
]]>
</Body>
<Summary>Eddy Cue, a senior vice president for Apple, denied that the company colluded with publishers to fix e-book prices.     </Summary>
<Website>http://www.nytimes.com/2013/06/14/technology/apple-negotiator-defends-tactics-in-e-book-trial.html?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31310/guest@my.umbc.edu/45b019482df5546f16578fcb3c309dbc/api/pixel</TrackingUrl>
<Tag>amazon-com-inc-amzn-nasdaq</Tag>
<Tag>apple-inc-aapl-nasdaq</Tag>
<Tag>cue-eddy</Tag>
<Tag>e-books-and-readers</Tag>
<Tag>jobs-steven-p</Tag>
<Tag>new</Tag>
<Tag>technology</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Thu, 13 Jun 2013 21:02:55 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="false" id="31306" important="false" status="posted" url="https://my3.my.umbc.edu/posts/31306">
<Title>New Resources for Registered Apple Developers</Title>
<Body>
<![CDATA[
    <div class="html-content"><p>As a Registered Apple Developer, you already have free access to developer tools and resources for creating iOS apps and Mac apps. Now you can take advantage of more great content, with access to pre-release documentation, videos, and sample code. You can also sign in to view discussions in the Apple Developer Forums and gain further insight into developing for iOS, OS X, and more. Sign in to <a href="https://developer.apple.com/membercenter/index.action" rel="nofollow external" class="bo">Member Center</a>.</p></div>
]]>
</Body>
<Summary>As a Registered Apple Developer, you already have free access to developer tools and resources for creating iOS apps and Mac apps. Now you can take advantage of more great content, with access to...</Summary>
<Website>https://developer.apple.com/news/index.php?id=6132013b</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/31306/guest@my.umbc.edu/2863fe4a6d4469ac0f1d615690cb504f/api/pixel</TrackingUrl>
<Tag>apple</Tag>
<Tag>developer</Tag>
<Tag>ios</Tag>
<Tag>ipad</Tag>
<Tag>iphone</Tag>
<Tag>ipod</Tag>
<Tag>objective-c</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Thu, 13 Jun 2013 20:20:00 -0400</PostedAt>
</NewsItem>

</News>
