1. Web Design
  2. HTML/CSS
  3. CSS

Building a CMS: Structure and Styling

With the increase of use of a Virtual Private Server (VPS), it is more feasible now than ever to roll out your own Content Management System (CMS). In this series of tutorials, I will show you a simple flat-file system CMS in several of the most used web languages. This tutorial focuses on the structure, theming, and syncing of the CMS.
Scroll to top
This post is part of a series called Building a CMS.
Building a CMS: goPress
Final product imageFinal product imageFinal product image
What You'll Be Creating

There has been a trend of “flat CMS design” webservers. This simply refers to a Content Management System (CMS) that does not store its information in a database. Instead, all information is stored in plain text files. Since many virtual private servers (VPS) these days are using RAM-based hard drives, this approach is faster and a bit more secure.

In this series of tutorials, I will show you how to create your own flat file system CMS using some standard web technology. These systems are not as full featured as others, but have the basics with a good response time.

With all the information on the hard drive, file organization becomes a big issue. With that in mind, the site information will be in a different directory than the styling and layout information. Also, each type of page has its own directory under the site folder with a parts directory for small parts of the CMS. This keeps everything in its own place and makes a flexible system.

Main Directory Structure

In the directory in which you are going to build the project, create the following directories: src, site, and themes. The src directory will contain the server code, the site directory is for all the site information, and the themes directory for the layout and theming information.

In the themes directory, you need to make a layouts and a styling directory. The layouts directory will contain the different web page layouts. By separating the layout information from the styling information, the themes become much more flexible. For now, there will be one layout called SingleCol.

For all the styling and layout creation, I am using Sass, Compass, and Susy. Sass is a Custom Style Sheet processing language. It gives a more robust way to create the CSS style sheets for your website. Compass is an extension to Sass. Sassy-buttons is a Sass extension for making nice-looking buttons on the website. Susy is also an extension for creating a grid layout system for your site.

Since Ruby is pre-installed on all Macs, you will not need to install it. To get Ruby on a Windows system, you will need to download Ruby’s Windows Installer. On Linux, you need to use your system’s package manager to install Ruby.

Once Ruby is on your system, you can install Sass, Compass, Sassy-buttons, and Susy with these command lines:

1
2
gem install sass
3
gem install sassy-buttons
4
gem install compass
5
gem install susy

For this tutorial, I am using Sass 3.4.16, Sassy-buttons 0.2.6, Compass 1.0.3, and Susy 2.2.5. Depending on your system’s configuration, you might have to run these commands with sudo before them.

Layouts

To get started creating layouts, run these commands in the SingleCol directory:

1
2
compass init

This will create the sass and stylesheets directories, and a file named config.rb. Since I like using css for the stylesheet directory, rename the stylesheets directory to css. Also, create a js directory for any needed JavaScript files for the layout. Open the config.rb file and make it look like this one:

1
2
require 'susy'
3
http_path = "/"
4
css_dir = "css"
5
sass_dir = "sass"
6
images_dir = "images"
7
javascripts_dir = "js"

Now, to create the basic layout of the website, create a file in the layout directory called template.html. In this file, add this code:

1
2
3
4
5
	
6
	
7
	
8
		{{{title}}}
9
	
10
	
11
	{{{head}}}
12
13
14
15
	
16
		
17
			
18
				{{{header}}}
19
			
20
			
21
				{{{navbar}}}
22
			
23
		
24
		
25
			{{{sidebar}}}
26
		
27
		
28
			{{{content}}}
29
		
30
		
31
			{{{footer}}}
32
		
33
	
34
	
35
36
37

This template creates a standard web page for the site. Each page has a header with a navigation bar, a single sidebar, a content area, and a footer area. The last thing loaded is the javascripts needed for the site.

Each section is represented with a Handlebar macro. The server expands the macros before giving it to the user.

In the sass directory, create a file called base.scss and place this code:

1
2
@import 'compass/reset';
3
@import 'susy';
4
5
$susy: (
6
  flow: ltr,
7
  math: fluid,
8
  output: float,
9
  gutter-position: after,
10
  container: auto,
11
  container-position: center,
12
  columns: 16,
13
  gutters: .25,
14
  column-width: false,
15
  global-box-sizing: content-box,
16
  last-flow: to,
17
  debug: (
18
    image: hide,
19
    color: rgba(#66f, .25),
20
    output: background,
21
    toggle: top right,
22
  ),
23
  use-custom: (
24
    background-image: true,
25
    background-options: false,
26
    box-sizing: true,
27
    clearfix: false,
28
    rem: true,
29
  )
30
);
31
32
body {
33
}
34
35
#wrap {
36
  @include container(16);
37
  width: 1024px;
38
  display:  block;
39
}
40
41
#headerwrap {
42
  @include span(16 of 16);
43
  margin-bottom: 20px;
44
}
45
46
#header {
47
  margin-top: 20px;
48
  margin-left: auto;
49
  margin-right: auto;
50
  width:    95%;
51
}
52
53
#content {
54
    @include span(11 of 16);
55
 }
56
57
.col1 {
58
    @include span(5 of 10);
59
}
60
61
.col2 {
62
    @include span(last 5 of 10);
63
}
64
65
#footer .col2 {
66
    width: auto;
67
}
68
69
.box {
70
  @include span(4 of 10);
71
}
72
73
#sidebar {
74
  @include span(last 4 of 16);
75
}
76
77
#footer {
78
  @include span(16 of 16);
79
}
80
81
/** CSS dropdown menu **/
82
83
#navigation  {
84
  margin-top: 20px;
85
  margin-left: auto;
86
  margin-right: auto;
87
  width:    95%;
88
}
89
90
#menuh-container {
91
  top: 1em;
92
  left: 1em;
93
  display: inline;
94
  width: 100%;
95
}
96
97
#menuh {
98
  margin-top: 1em;
99
  display: inline;
100
  width: 100%;
101
}
102
103
#menuh ul li {
104
  display: inline-block;
105
  width: fit-content;
106
}
107
108
#menuh a
109
  {
110
  text-align: center;
111
  display:block;
112
  white-space:nowrap;
113
  margin:0;
114
  padding: 5px;
115
  text-decoration: none;
116
  }
117
118
#menuh ul
119
  {
120
  list-style:none;
121
  margin: 0px 20px 0px 20px;
122
  padding: 0px;
123
  }
124
125
#menuh li
126
  {
127
  position:relative;
128
  min-height: 1px;
129
  vertical-align: bottom; 
130
  width: fit-content;
131
  }
132
133
#menuh ul ul
134
  {
135
  position:  absolute;
136
  z-index:  500;
137
  top: 50px;
138
  left: 20px;
139
  display:  none;
140
  padding: 0.5em;
141
  margin:  -1em 0 0 -1em;
142
  }
143
144
  #menuh ul ul li {
145
    width: 100%;
146
  }
147
148
#menuh ul ul li  a {
149
    text-align:  left;
150
}
151
152
#menuh ul ul ul
153
  {
154
  left: 90px;
155
  }
156
157
div#menuh li:hover
158
  {
159
  cursor:pointer;
160
  z-index:100;
161
  }
162
163
div#menuh li:hover ul ul,
164
div#menuh li li:hover ul ul,
165
div#menuh li li li:hover ul ul,
166
div#menuh li li li li:hover ul ul
167
{display:none;}
168
169
div#menuh li:hover ul,
170
div#menuh li li:hover ul,
171
div#menuh li li li:hover ul,
172
div#menuh li li li li:hover ul
173
{display:block;}
174
175
/* End CSS Drop Down Menu */

This sass code loads in the compass reset styles to neutralize the browser defaults. Then it loads and sets up susy for creating the proper grid layout for all the elements of the web page.

The css navigation system is after the page defines. The hidden drop-downs for the menus become visible with mouse-over definitions. This gives a css only menu system.

All of these styles define the basic structure of the website. Nothing here creates a look to the page, just its positioning. All styling gets handled by the styling content.

Styles

For the styling directory, create a directory called Basic. Initialize the sass information as done for the layouts/SingleCol directory. In this directory, run the following command line:

1
2
compass init

This will create the sass and stylesheets directories, and a file named config.rb. Since I like using css for the stylesheet directory, rename the stylesheets directory to css. Also, create a js directory for any JavaScript for creating the theme. Open the config.rb file and make it look like this one:

1
2
require 'sassy-buttons'
3
http_path = "/"
4
css_dir = "css"
5
sass_dir = "sass"
6
images_dir = "images"
7
javascripts_dir = "js"

For styling buttons on the website, I like to use sassy-buttons. Therefore, it is required first, and then the directory structure.

In the Basic/sass directory, create the Basic.scss file with this information:

1
2
// Welcome to Compass.
3
// In this file you should write your main styles. (or centralize your imports)
4
// Import this file using the following HTML or equivalent:
5
// 
6
//
7
@import 'compass/css3';
8
@import 'sassy-buttons';
9
10
$style-color1: rgb(247, 237, 222);
11
$style-color2: #ffedd1;
12
$style-color3: rgb(245, 213, 166);
13
$style-color4: #f0d5ad;
14
15
//
16
// Clear Fix
17
//
18
.clearfix:after {
19
    content: '.';
20
    display: block;
21
    clear: both;
22
    visibility: hidden;
23
    line-height: 0;
24
    height: 0;
25
}
26
27
.clearfix {
28
    display: inline-block;
29
}
30
31
html[xmlns] .clearfix {
32
    display: block;
33
}
34
35
* html .clearfix {
36
    height: 1%;
37
}
38
39
//
40
// Main Styling for Wood.
41
//
42
@mixin standardsize {
43
    padding-top: 10px;
44
    padding-left: 15px;
45
    font-size: 19px;
46
    line-height: 1.25em;
47
}
48
49
body {
50
    background-color: $style-color2;
51
52
    input[type='button'] {
53
        @include sassy-button('shiny', 10px, 16px, $style-color1, darken($style-color1, 20%), #000, bold);
54
    }
55
56
    .button {
57
        @include sassy-button('shiny', 10px, 16px, $style-color1, darken($style-color1, 20%), #000, bold);
58
        display: inherit;
59
        margin-left: auto;
60
        margin-right: auto;
61
        margin-top: 10px;
62
        margin-bottom: 10px;
63
        text-align: center;
64
    }
65
66
    #wrap {
67
        background-color: $style-color1;
68
        @include border-radius(.6em, .6em);
69
        margin-top: 10px;
70
        margin-bottom: 10px;
71
        border: 4px solid $style-color4;
72
73
        #header {
74
            background-color: $style-color2;
75
            @include border-radius(15px);
76
            background-repeat: no-repeat;
77
            border: 2px solid $style-color3;
78
            height: 130px;
79
            text-align: left;
80
            margin-top: 20px;
81
            font-size: 3em;
82
83
            h1 {
84
                a:link, a:visited {
85
                    color: #000;
86
                    text-decoration: none;
87
                }
88
                padding-top: 40px;
89
                padding-left: 20px;
90
            }
91
            h6 {
92
                font-size: .4em;
93
                font-style: italic;
94
                padding-left: 20px;
95
            }
96
        }
97
        #sidebar {
98
            background-color: $style-color2;
99
            @include border-radius(.6em, .6em);
100
            padding: .6em;
101
            vertical-align: text-top;
102
            overflow: hidden;
103
            margin-right: .5em;
104
            border: 2px solid $style-color3;
105
            hr {
106
                color: $style-color2;
107
                background-color: $style-color2;
108
            }
109
            p, ul, li {
110
                @include standardsize;
111
            }
112
            ul li {
113
                list-style-type: disc;
114
                margin-left: 25px;
115
                padding: 0;
116
                border: 0;
117
                outline: 0;
118
                font-size: 100%;
119
                vertical-align: baseline;
120
                background: transparent;
121
            }
122
            li {
123
                margin-bottom: 10px;
124
            }
125
            h1, h2, h3, h4, h5, h6 {
126
                @include standardsize;
127
                font-weight: bold;
128
                margin-top: .25em;
129
                margin-bottom: .25em;
130
            }
131
            h1 {
132
                font-size: 2.5em;
133
            }
134
            h2 {
135
                font-size: 2em;
136
            }
137
            h3 {
138
                font-size: 1.5em;
139
            }
140
            h4 {
141
                font-size: 1em;
142
            }
143
            h5 {
144
                font-size: .8em;
145
            }
146
            h6 {
147
                font-size: .6em;
148
            }
149
            input[type='button'] {
150
                margin-left: 120px;
151
                clear: both;
152
            }
153
        }
154
        #content {
155
            input[type='button'] {
156
                margin-left: 200px;
157
                clear: both;
158
            }
159
            h1, h2, h3, h4, h5, h6 {
160
                @include standardsize;
161
                font-weight: bold;
162
                margin-top: .25em;
163
                margin-bottom: .25em;
164
            }
165
            h1 {
166
                font-size: 2.5em;
167
            }
168
            h2 {
169
                font-size: 2em;
170
            }
171
            h3 {
172
                font-size: 1.5em;
173
            }
174
            h4 {
175
                font-size: 1em;
176
            }
177
            h5 {
178
                font-size: .8em;
179
            }
180
            h6 {
181
                font-size: .6em;
182
            }
183
            hr {
184
                margin-top: 30px;
185
                margin-bottom: 30px;
186
            }
187
            p, ul, li, details, summary, pre {
188
                @include standardsize;
189
            }
190
            details {
191
                p, pre {
192
                    margin-left: 25px;
193
                }
194
            }
195
            ul li {
196
                list-style-type: disc;
197
                margin-left: 25px;
198
                padding: 0;
199
                border: 0;
200
                outline: 0;
201
                font-size: 100%;
202
                vertical-align: baseline;
203
                background: transparent;
204
            }
205
            li {
206
                margin-bottom: 10px;
207
            }
208
            .box {
209
                clear: both;
210
                background-color: $style-color4;
211
                float: none;
212
                margin-left: auto;
213
                margin-right: auto;
214
                margin-top: 1.0em;
215
                margin-bottom: 1em;
216
                @include border-radius(.6em, .6em);
217
                display: block;
218
                padding: .5em;
219
            }
220
            img {
221
                @include border-radius(10px);
222
                margin: 20px auto 20px auto;
223
            }
224
        }
225
        #footer {
226
            border-top: 5px;
227
            border-style: solid;
228
            border-color: $style-color3;
229
            @include border-radius(.6em, .6em);
230
            margin-top: 30px;
231
            p {
232
                margin-bottom: .6em;
233
                @include standardsize;
234
                margin-right: 15px;
235
            }
236
        }
237
    }
238
}
239
240
// CSS dropdown menu
241
#navigation {
242
    text-align: left;
243
    border: 2px solid $style-color3;
244
    background-color: $style-color2;
245
    @include border-radius(15px);
246
}
247
248
#menuh {
249
    font-size: 1.3em;
250
    font-family: arial, helvetica, sans-serif;
251
    background-color: $style-color1;
252
}
253
254
#menuh ul {
255
    background-color: $style-color2;
256
}
257
258
#menuh ul ul {
259
    background-color: $style-color2;
260
    @include border-radius(15px);
261
    border: 2px solid $style-color3;
262
}
263
264
#menuh a {
265
    background-color: $style-color2;
266
    color: #000;
267
}
268
269
#menuh a:link, #menuh a:visited, #menuh a:active {
270
    color: #000;
271
    background-color: $style-color2;
272
}
273
274
#menuh a:hover {
275
    color: #000;
276
    background-color: $style-color4;
277
    @include border-radius(5px);
278
}
279
280
// End CSS Drop Down Menu
281
// Misc classes
282
.picture {
283
    border: 3px solid $style-color3;
284
    @include border-radius(8px);
285
    float: left;
286
    margin: 5px 15px 15px 15px;
287
}
288
289
a:link, a:visited {
290
    color: darken($style-color1, 50);
291
    text-decoration: none;
292
}
293
294
strong {
295
    font-weight: bold;
296
}
297
298
table {
299
    margin: 20px;
300
    border: 3px solid;
301
    @include border-radius(10px);
302
    border-color: lighten($style-color2, 6);
303
    th {
304
        text-align: center;
305
        font-weight: bold;
306
        padding: 10px 0 10px 0;
307
    }
308
    tbody {
309
        td {
310
            padding: 10px;
311
        }
312
        tr:nth-child(2n+1) {
313
            background-color: darken($style-color2, 5);
314
        }
315
        tr:nth-child(even) {
316
            background-color: lighten($style-color2, 2.5);
317
        }
318
    }
319
}
320
321
#commentSpacer {
322
    width: 100%;
323
    margin-top: 20px;
324
    margin-left: 15px;
325
}
326
327
.tutorial_excerpt {
328
    margin-left: 20px;
329
}
330
331
.tutorial_thumbnail {
332
    float: left;
333
    margin-right: 20px;
334
    margin-left: 20px;
335
    margin-bottom: 20px;
336
}
337
338
.tutorial_wrap {
339
    margin-bottom: 50px;
340
    float: left;
341
}
342
343
img.wp-post-image {
344
    -moz-border-radius: 15px;
345
    border-radius: 15px;
346
    box-shadow: 10px 10px 5px gray;
347
}
348
349
.showcode {
350
    margin: 20px auto 20px 30px;
351
    -moz-border-radius: 15px;
352
    border-radius: 15px;
353
    border: $style-color4 3px;
354
    border-style: solid;
355
    background: white;
356
}
357
358
#socialmedia {
359
    width: 700px;
360
    margin-top: 20px;
361
    margin-left: 15px;
362
}
363
364
#socialbuttons {
365
    margin: auto;
366
}
367
368
#socialbuttons a {
369
    opacity: 0.8;
370
    filter: alpha(opacity = 80);
371
    -webkit-transition: all ease-in-out 0.2s;
372
    -moz-transition: all ease-in-out 0.2s;
373
    -ms-transition: all ease-in-out 0.2s;
374
    -o-transition: all ease-in-out 0.2s;
375
    transition: all ease-in-out 0.2s;
376
}
377
378
#socialbuttons a:hover {
379
    opacity: 1;
380
    filter: alpha(opacity = 100);
381
}
382
383
#socialbuttons a {
384
    display: inline-block;
385
    height: 28px;
386
    width: 30px;
387
    background-image: url(/images/ico-subscribe-social.png);
388
    background-repeat: no-repeat;
389
}
390
391
#socialbuttons a.twitter {
392
    background-position: -30px 0;
393
}
394
395
#socialbuttons a.facebook {
396
    background-position: -60px 0;
397
}
398
399
#socialbuttons a.googleplus {
400
    background-position: -210px 0;
401
}
402
403
dl {
404
    margin-left: 20px;
405
    margin-top: 20px;
406
    margin-bottom: 20px;
407
    font-size: 19px;
408
    line-height: 1.25em;
409
}
410
411
dt {
412
    margin-left: 20px;
413
    margin-bottom: 20px;
414
    font-weight: bold;
415
}
416
417
dd {
418
    margin-left: 40px;
419
    margin-bottom: 20px;
420
}

This code defines how the website will look. It defines the background, coloring, fonts, etc. that make up the styling for a typical website.

The styling/Basic directory contains the files needed for the default look of the 404 page, header, footer, and sidebar parts of the website. Therefore, create a file called 404.html and place this code:

1
2
404 Page
3
4
Sorry, we could not find the page.

This is a basic 404 error page. You have to be careful of the information given here, as you do not want to reveal too much information about how your site works. Since this will be placed in the contents area of the page, it will be easy for the user to navigate away from it.

Next, create the header.html file with this content:

1
2
Test Site
3
A New Approach
4

This is just a bare-bones header that is non-descriptive, but it gives the CMS something to show.

Next, create the footer.html file with this content:

1
2
<footer>
3
[Column1]
4
    <p>Copyrighted 2012 by <a href="{{{WebAddress}}}/">Your Company</a>
5
[/Column1]
6
[Column2]
7
	<p>Running on a flat CMS server!</p>
8
[/Column2]
9
</footer>

Next, create the sidebar.html file with this content:

1
2
A Sidebar
3
This is a basic sidebar that can have other times.

Again, these are place-holders. All of these files get copied to the site/parts directory and changed according to the site’s needs. These are here so that the server has something with their names to use in the server in case the user forgets to create them.

Site Structure

With the theming and layouts defined, it is time to create the basic content and structure for the actual site. In the site directory, create the parts, pages, posts, images, css, js directories.

Parts

The parts directory will contain small snippets of html/css/javascript that will make a single unit placed in multiple locations of the website. These parts are loading into the server and combined with the page contents as needed. For our demo site, create the following parts:

  • footer.html with this code:
1
2
<footer>
3
    <p style="float: left;">Copyrighted 2012 by <a href="{{{WebAddress}}}/">Your Company</a>
4
	<p style="float: right;">Running on a flat CMS server!</p>
5
</footer>
6
<script type="text/javascript">
7
window.PageName = "{{{PageName}}}";
8
</script>
  • head.html with this code:
1
2
  • header.html with this code:
1
2
Test Site
3
Flat File System CMS
  • navbar.html with this code:
1
2
 
3
 
4
    
5
     
6
         Pages
7
         
8
             
9
                 Flat CMS
10
             
11
         
12
     
13
     
14
        Blog
15
     
16
     
17
         News
18
     
19
     
20
         About
21
     
22
 
23
24
  • sidebar.html with this code:
1
2
Side Bar
3
  • socialmedia.html with this code:
1
2
3
    
4
        
5
6
        
7
    
8
    
9
    
10

The server loads these parts using the name without the extension in the Handlebar template for expansion. For example, anywhere the socialmedia.html part needs to be placed, you place the macro {{{socialmedia}}} there. Also, these parts can be HTML, Markdown, or any other format that the server can handle. In the servers I will be making, the supported types of files are HTML, Jade/Amber, and Markdown. I will get into these details in the actual server creation tutorials.

Pages

All of the pages for the site will be placed in the pages directory. For now, create the following files with their content:

  • main.html with this code:
1
2
Flat CMS Test Site
3
This is the Main page of the test site.
  • flatcms.md with this code:
1
2
### Flat CMS Server
3
4
This is a page about the flat CMS server. 
  • about.md with this code:
1
2
### About
3
4
This would be a standard about page.

These are the demo pages for the site. The only required file is main.html as the server will load this page content into memory and serve from memory. That helps to speed up the loading of the front page of the website. The other two pages have the md extension because they are in Markdown format. The server will translate the content to HTML before embedding in the page layout.

In general, pages contain information that doesn’t change much over time. They give the viewer information about the site, its purpose and goals.

Pages can be hierarchical in nature by creating directories and sub-directories with pages. These directory names create the addresses to these pages’ directory.

Posts

Unlike pages, posts are items that get added regularly, for example, daily/weekly/monthly blog posts and news items. This area is expected to change often. In the posts directory, create two new directories: blogs and news. In each of these directories, create a directory flatcms. These will contain the blog posts and news items for the Flat CMS website.

In the posts/blogs/flatcms directory, create the following files:

  • index.amber with these contents:
1
2
h3 Flat CMS Blog
3
4
p This is a rambling blog about a flat CMS.
5
6
mixin article($title, $link, $excerpt, $date)
7
	div.entry
8
		div.tutorial_wrap
9
			div.tutorial_div
10
				a[href=$link]
11
					h3 #{$title}
12
				h5 #{$date}
13
				p.tutorial_excerpt #{$excerpt}
14
	div.clear
15
16
+article("Flat CMS Running", "/posts/blogs/flatcms/flatcms", "Flat CMS Test Server is Running!", "August 12, 2015")
  • flatcms.md with these contents:
1
2
The New Server is Running
3
----
4
5
After much work and programming, the flat CMS server is running.  Stay tuned for more news!
6
7
{{{socialmedia}}}

The index.amber is a Jade template to define the different posts in the blog. The Jade HTML template system makes it easy to add new content with an exact format. The parameters to the macros make up the different items. You can find more information about Jade on Tuts+.

Here, the extension used is amber because the Go language equivalent of Jade is Amber. Since that was where I started, that is how I made it. If you want to change the extension, then remember to change it in the appropriate server code as well.

In the posts/news/flatcms directory, create the following files:

  • index.amber with these contents:
1
2
h3 Flat CMS News
3
4
p Here is where all the news about what I am doing is found. Please come back often to check it out!
5
6
mixin article($title, $link, $excerpt, $date)
7
	div.entry
8
		div.tutorial_wrap
9
			div.tutorial_div
10
				a[href=$link]
11
					h3 #{$title}
12
				h5 #{$date}
13
				p.tutorial_excerpt #{$excerpt}
14
	div.clear
15
16
+article("Flat CMS is Running", "/posts/news/flatcms/flatcms", "The Flat CMS Test Server is Running!", "August 12, 2015")
  • flatcms.md with these contents:
1
2
The New Server is Running
3
----
4
5
After much work and programming, I finally have everything moved over to a goPress server that I wrote myself. I will be making this available for you too. Stay tuned!
6
7
{{{socialmedia}}}

This creates the news items for the demo site. In my site, I use the same structure for tutorials and code demo pages.

Images

All websites have pictures. In this setup, all pictures are in the site/images directory. For this demo site, only the social media icons will be placed here. You can get the image file from the download file.

Site CSS

Even with the layout css and styling css, there will be times you will want special css rules. The site/css directory contains all css files that put those finishing touches to the website. All the layout, styling, and site/css files will be compiled together in to one css file. Therefore, create the site/css/final directory to place this compiled file. Now, create the site/css/site.css file with these contents:

1
2
.clear {
3
  clear: both;
4
  height: 0px;
5
}

Not much in here—just a definition for a clear class. You can add what you want, but it should be something that does not fall into the layout or styling category.

Site Scripts

The site/js directory contains all the special JavaScript files for the site. These will be compiled together and minimized for faster site loading. For now, create the site/js/final directory for the compiled script and a site/js/01-site.js file with these contents:

1
2
;
3
//
4
// File:         Site.js
5
//
6
// Description:   The JavaScript file for the site.
7
//
8
jQuery(document).ready(function () {
9
	//
10
	// Code here will be ran once a page is loaded.
11
	//
12
});

There is not much here right now. But, as your site needs custom JavaScript, it can be placed here.

Since the scripts will be compiled together, I number them in the order needed for loading. The routine for compiling the scripts together will load them in numerical order.

Automating With Gulp

The easiest way to speed up a web page load is to have as few HTTP requests as possible. Therefore, it is best to combine all CSS and JavaScript files into one file each. The best way to compile these files is with a build script. Performing it every time the server gets a request is a waste of processing time.

My choice of automation script runners is Gulp. Gulp runs on Node.js. Therefore, please go to the Node.js website and download the program for your system. Once you have Node.js installed, you can install Gulp with the following:

1
2
npm install --global gulp
3
npm install --global gulp
4
npm install --global gulp-compass
5
npm install --global gulp-autoprefixer
6
npm install --global gulp-compressor
7
npm install --global gulp-concat

This will install all of the Gulp and Gulp modules that I use in the build script. Now, at the top of your directory, create the gulpfile.js file with these contents:

1
2
// Requirements
3
var gulp = require('gulp'),
4
	 compass = require('gulp-compass'),
5
	 prefix = require('gulp-autoprefixer'),
6
	 compressor = require('gulp-compressor'),
7
	 concat = require('gulp-concat');
8
9
// Defines path to sass
10
var Theme = "Basic";
11
var Layout = "SingleCol";
12
var themesassRoot = 'themes/styling/' + Theme;
13
var layoutsassRoot = 'themes/layouts/' + Layout;
14
15
// Gulp task
16
gulp.task('theme-compass-to-css', function(){
17
	return gulp.src(themesassRoot+'/sass/Basic.scss')
18
			 .pipe(compass({
19
                config_file: themesassRoot + '/config.rb',
20
                css: themesassRoot + '/css',
21
                sass: themesassRoot + '/sass',
22
                require: 'sassy-buttons'
23
                }))
24
			 .pipe(prefix("last 3 versions"))
25
			 .pipe(gulp.dest(themesassRoot + '/css'))
26
});
27
28
gulp.task('layout-compass-to-css', function(){
29
	return gulp.src(layoutsassRoot+'/sass/base.scss')
30
			 .pipe(compass({
31
                config_file: layoutsassRoot + '/config.rb',
32
                css: layoutsassRoot + '/css',
33
                sass: layoutsassRoot + '/sass',
34
                require: 'susy'
35
                }))
36
			 .pipe(prefix("last 3 versions"))
37
			 .pipe(gulp.dest(layoutsassRoot + '/css'))
38
});
39
40
gulp.task('watch-compass', function(){
41
	// What to watch
42
	gulp.watch(themesassRoot + '/sass/Basic.scss', function(){
43
		// What to run
44
		gulp.run('theme-compass-to-css');
45
	});
46
	gulp.watch(layoutsassRoot + '/sass/Basic.scss', function(){
47
		// What to run
48
		gulp.run('layout-compass-to-css');
49
	});
50
});
51
52
gulp.task('all-compass', ['theme-compass-to-css', 'layout-compass-to-css']);
53
54
// js compressor
55
gulp.task('js', function () {
56
    gulp.src([ layoutsassRoot +'/js/*.js', themesassRoot + '/js/*.js', 'site/js/*.js'])
57
        .pipe(compressor())
58
        .pipe(concat("final.js"))
59
        .pipe(gulp.dest('site/js/final'));
60
});
61
62
// css compressor
63
gulp.task('css', ['all-compass'], function () {
64
    gulp.src([layoutsassRoot +'/css/*.css', themesassRoot + '/css/*.css', 'site/css/*.css'])
65
        .pipe(compressor())
66
        .pipe(concat("final.css"))
67
        .pipe(gulp.dest('site/css/final'));
68
});
69
70
gulp.task('default', ['all-compass', 'js', 'css']);

This will compile all of the CSS and JavaScript into a single file: in the site/css/final/final.css file for the CSS, and in the site/js/final/final.js file for the JavaScript. It will also add the browser prefix rules for the CSS. Just run in the top directory the command:

1
2
gulp

Gulp will compile all of our files and leave them in the proper location. Each task defined in the gulpfile.js can be run individually by giving the task name after the gulp command. You can learn more about Gulp on Tuts+.

Server Configuration File

All servers need configuration information. Therefore, in the root of the directory, create the file server.json with this information:

1
2
{
3
    "CurrentLayout": "SingleCol",
4
    "CurrentStyling": "Basic",
5
    "ServerAddress": "localhost:8080",
6
    "SiteTitle": "Flat CMS Test Site",
7
    "Sitebase": "./site/",
8
    "TemplatBase": "./themes/",
9
    "Cache": false,
10
    "MainBase": ""
11
}

This json file describes information about the layout to use, the styling to use, the address and port the server should listen to, the main name for the site with a sub-title, a caching flag to turn on and off caching for debugging purposes, and the location of the different directories used for the site. By supplying this information to the server in a json file, the server can be flexible, with less hard-coded information.

Uploading the Site to a Server

Most people use an FTP client to copy the files to their server. This is easy to do, but varies greatly regarding the system and programs used. But there are some alternatives.

You can setup a Dropbox daemon to load your site from your Dropbox account. The Dropbox Wiki site has detailed instructions for setting this up. The only problem is the files are automatically uploaded to the server when you make any change. Sometimes, you will want to make changes without them going to the server. If this is the case, have a non-Dropbox location of all the site’s files and a Dropbox location as well. When done, create a task in your Gulp file to copy the new site files over to the Dropbox location.

Dropzone 3 Setup for CMS UploadingDropzone 3 Setup for CMS UploadingDropzone 3 Setup for CMS Uploading
Dropzone 3 Setup for CMS Uploading

My preferred approach is to use Dropzone 3. You can program Dropzone 3 with Ruby or Python to perform any type of action on a file that is a dropped on it. It also has many built-in functions. There is a file action built in for uploading to an FTP/SFTP site. I create one Dropzone 3 target for each of the main directories on my site. Then, when I want to change or add a file, I simply drag it to the appropriate directory dropzone target. You can learn more about Dropzone 3 with my tutorial Writing Dropzone 3 Actions.

Conclusion

These basic files will create a website that looks like this:

Demo Site in BrowserDemo Site in BrowserDemo Site in Browser
Demo Site in Browser

This is only the beginning! Now, with the site structure laid out, it is time to start building web servers. Please join me in the next tutorial where I will build a Go language based web server for this demo site.