Basic Laravel Site

Christopher Pitt
Aug 14, 2014 · 6 min read

I frequently speak to developers who are just getting into the Laravel framework. Usually I’ll recommend excellent resources, such as and Code Bright, but it’s also nice to be able to point them towards something I’ve written. I’m already preparing this content (for workshops and user-groups), so I might as well share it where more people can see it.

Today we’ll look at how to build a simple website in Laravel. By simple, I mean that we’ll only use simple parts of the framework, to build a static website. The parts I have in mind are route callbacks, templates and helpers.


Before we begin; you should have PHP 5.4+ (with Mcrypt). This is a requirement for installing Laravel 4, though I won’t go through the details here (as it’s not the focus of this post).

You’ll also need Composer. You can find instructions on how to install it at

Installing Laravel

If your system meets the above requirements, you should be able to install Laravel with the following command:

$ composer create-project "laravel/laravel:4.*"

Installing laravel/laravel (v4.2.0)
- Installing laravel/laravel (v4.2.0)
Loading from cache

We can start a testing server by heading into the created directory, and running:

$ php artisan serve

Laravel development server started on http://localhost:8000

Open this up in your browser, and you should see the welcome screen!

Creating Layouts

Layout templates are templates which contain HTML common to all pages of the website you want to build. We wouldn’t want to repeat basic page elements on every page, so (by placing them in a layout template) we can inherit them as easily as a subclass inherits from its parent class:

<!doctype html>
<html lang="en">
<title>My Website</title>
<link rel="stylesheet" href="/css/shared.css" />
<div class="header">
<div class="content">

This is from app/views/layout.blade.php

This simple layout introduces two Blade tags. The @include tag is similar to PHP’s include() function, with a few added benefits. It will send data along to the included file (more on this in a bit) and it will automatically complete the file name.

Blade is the name of Laravel’s built-in template engine.

The @yield tag will output some stored content. We’ll see how this works in a bit, but first let’s render this view. To do that, we need to change our routes file a bit:


Route::get("/", function() {
return View::make("layout");

This is from app/routes.php

We’ll also need to update our config settings (to show errors):


return array(
"debug" => true,
...other code

This is from app/config/app.php

We change that configuration setting because we want to be able to see detailed error messages as we develop the website. When we refresh the browser, we should see an error message.

This is because we’ve not yet defined the header include. What’s interesting to note is how the View::make() method completed the layout template’s name for us. If templates end in .php then Laravel renders them as normal PHP template files. If they end in .blade.php then PHP renders them like Blade templates.

Creating Links

We should create the header include next:

<div class="cover">
<img src="/img/profile.jpg" />
<div class="navigation">
<a href="{{ URL::route('connect') }}">Connect</a>
<a href="{{ URL::route('create') }}">Create</a>
<a href="{{ URL::route('contact') }}">Contact</a>

This is from app/views/include/header.blade.php

@section tags are linked to @yield tags. Sections are stored blocks of HTML which can be yielded in other places. I’m closing the @section tag with @show which means that this HTML will immediately render. I could also close the @section with @stop which would still store the block of HTML, but it wouldn’t be shown until yielded.

{{ and }} are a set of Blade tags which mean the same thing as <?php echo and ?>. This means you can use them to echo a variable. In this case we’re using the URL::route() to generate the named routes we’re about to define…

A route is just a name we give to executable code which is matched to a special pattern.

We’ve already seen routes in action, but let’s add a few more:


Route::get("/", function() {
return Redirect::route("connect");

Route::get("/connect", ["as" => "connect", function() {
return View::make("connect");

Route::get("/create", ["as" => "create", function() {
return View::make("create");

Route::get("/contact", ["as" => "contact", function() {
return View::make("contact");

This is from app/routes.php

The first time we saw this file, it had just the one route. We modified that route to render the layout template, but we’ve since changed it to redirect to the connect route. This means visitors will automatically be redirected to /connect when they visit the website.

Creating Pages

We should make these three templates (even though they’re only going to contain dummy data):

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc pellentesque posuere nunc, at laoreet augue. Donec
ultricies eu mi sit amet dictum. Maecenas ut posuere
ligula. Donec ut mauris vitae orci faucibus suscipit ac
et dui. Quisque sed massa non tortor euismod accumsan.
Praesent posuere, velit vitae convallis convallis, lacu
s sapien fringilla dolor, ut accumsan enim dolor id sem.
Sed augue nisi, convallis sed condimentum sed, aliquet
a mauris.

This is from app/views/connect.blade.php, app/views/create.blade.php and app/views/contact.blade.php

Highlighting Links

We’re now able to click through the navigation links, but it still looks mighty ugly. We should add some styling, but it would also be neat if we could highlight the current navigation item. To do that, we’ll need to make a small change to the header include:

<div class="cover">
<img src="/img/profile.jpg"/>
<div class="navigation">
<a class="{{ Route::is('connect') ? 'active' : '' }}"
href="{{ URL::route('connect') }}">Connect</a>
<a class="{{ Route::is('create') ? 'active' : '' }}"
href="{{ URL::route('create') }}">Create</a>
<a class="{{ Route::is('contact') ? 'active' : '' }}"
href="{{ URL::route('contact') }}">Contact</a>

This is from app/views/include/header.blade.php

Finally, add the following styles:

body {
padding : 0;
margin : 0;
color : #282828;
font-family : helvetica, arial, sans-serif;
font-size : 18px;
line-height : 32px;

.header {
position : relative;
background : #282828 url("/img/cover.png") no-repeat;
height : 500px;
margin : 0 0 200px 0;

.header img {
position : absolute;
width : 120px;
height : 120px;
border-radius : 100%;
border : 3px solid #fff;
margin : -60px 0 0 -60px;
left : 50%;
top : 500px;

.navigation {
position : absolute;
width : 100%;
top : 600px;
text-align : center;

.navigation a {
padding : 20px 0 5px 0;
margin : 0 10px 15px 10px;
font-size : 20px;
color : #333;
font-family : helvetica, arial, sans-serif;
text-decoration : none;
text-transform : uppercase;
border-bottom : 3px solid #fff;

.navigation a:hover, .navigation {
color : #228E47;
border-bottom : 3px solid #228E47;

.content {
margin : 0 auto;
width : 700px;
padding : 0 0 50px 0;
text-align : justify;

This is from public/css/shared.css

One Final Note

You remember how we changed the debug setting to true (so that we could see the content of error messages)? You need to remember to change that back to false. It’s bad for detailed error messages to be shown on live sites, so when you’re not in a local environment (where it’s safe to see that kind of information) debugging should not be left enabled.

    Christopher Pitt

    Written by

    Programming → Robotics → Minecraft

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade