A Brief Guide to Website Project File Structure and Management
Hacks /haks/: Small strays from a well-intended project. Slight inconsistencies from designers that make a site look polished, but make code as difficult to control as Skynet (if you != nerd { then Google it}).
Where exactly does one place this self-aware code, allowing it to fall well within the conformities and standards we’ve set for all other code? How does one ensure that after the monster has been created, the monster will stay within its confines—and not spread itself like a virus across every snippet of the project, with each iteration?
Why You Should Use a File Structure
A project needs to be maintainable, consistent, and easy to understand. When another developer jumps into the project to terminate Skynet, will they know which files to work on? Maintainability and consistency—both within a project and throughout multiple projects—is the goal.
A proper file structure is the first step towards that goal.
File structure can help set a standard for a project. It’s the footprint of a site, and will be followed 90% of the time if done well. As many code style guides will tell you, consistency is key. Developers tend to follow the base structure of the project’s initiator as a courtesy, and as a way to make sure a project stays maintainable and understandable. If a project begins with a particular structure, that structure should be adhered to from beginning to end, as it sets expectations.
Here are a couple of caveats to keep in mind:
- File structure shouldn’t be the end-all, be-all of a well-developed website. It’s a starting point, and shouldn’t become a relentlessly daunting consideration for the first three weeks of the project timeline.
- File structure should make sense, but not at the expense of the ability to complete a project. At some point, code must be written.
The following is how the development team at Zion & Zion tend to set up our project structure. These aren’t concrete, must-use, structures. We’ve grown into them organically, adding to and taking from them little by little for each project. They are suggestions. I expect you to adjust them to your liking.
Structure 1: Small Projects
A small project usually consists of a single page. Small projects really don’t require many files, and don’t hold a lot of meat and potatoes. They’re generally for things like landing pages. Google ad pages focus mainly on conversions, so they’re generally simplistic and straightforward, don’t include a Content Management System (CMS), and usually need minimal dynamic content.
There really isn’t a need for more than one stylesheet or script for these smaller projects. One of each would suffice, so the structure tends to be fairly flat. That said, breaking them up by screen size and functionality is usually enough for maintainability.
- scripts/
- scripts.js
- styles/
- _import.less
- _variables.less
- _mixins.less
- xs.less
- sm.less
- md.less
- lg.less
- images/
- fonts/
For smaller projects, Codekit comes in handy for jumping into the code right away. Structurer is also great for setting up the files quickly and consistently across small projects.
Structure 2: Large Projects
Large projects are typically full-blown websites. They are usually powered by a CMS (content management system) such as WordPress or Drupal, and can even be e-commerce sites using catalog tools such as Magento. They have multiple pages, most of which are templated, with a few unique pages such as the home page or contact page.
For these, one should really consider a build step and a templating language. Twig, for instance, is a favorite here at the office. It comes bundled in Drupal, and WordPress has a neat plugin for it.
Here’s an example of a WordPress theme asset structure:
- assets/
- development/
- images/
- fonts/
- styles/
- _import.less
- globals/
- variables.less
- mixins.less
- scaffolding.less
- components/
- navbar.less
- accordion.less
- pages/
- front-page.less
- scripts/
- _import.js
- globals/
- components/
- navbar.js
- accordion.js
- pages/
- front-page.js
- contact.js
- bower
- production/
- fonts/
- images/
- styles/
- styles.css
- styles.min.css
- scripts/
- scripts.js
- scripts.min.js
- scripts.min.js.map
- development/
Here, third-party tools are handled by the Bower package manager, and the styles and scripts are divided far more than in the small project structure. Each component’s less file holds styles for each screen size. The _import.less and _import.js pull in the styles or scripts at compile-time, and send those files to our production folder, which mirrors a similar structure. Grunt concatenates and minifies scripts, compiles less, minifies images, and copies fonts into the appropriate production folders.
Structure 3: Componentized Builds
Componentized builds are projects which have a very consistent visual adherence. They include several pieces that always appear and function the same, regardless of their position on the screen. In general, these are web applications—and they can get very large, very quickly. However, their structure tends to be less complex than the large projects, because there’s less need to account for uniquities.
Keep in mind that web applications generally don’t have “pages.” Instead, they contain “areas” that are built with tools such as angular.js, using data that is passed to templates for each area of the site. Build tools such as grunt, scaffolding tools such as yeoman, and methodologies such as BEM are important for quick, scalable development.
- global/
- variables.less
- variables.js
- component/
- button/
- button.less
- button.js
- button.tmpl
- button.png
- accordion/
- accordion.less
- accordion.js
- accordion.tmpl
- button/
Here, config files determine which components are loaded, which area they are loaded into, and configure the CSS and JavaScript to compile and load dynamically as necessary. Each component is self-contained, and can define sub-areas to import other components within them. This can be as complex or simple as needed, and the build step can be completely automated.
The above is a very simplistic representation of the BEM file structure, which is even more robust and can handle just about anything one might need for large web applications.
Conclusion
There are at least a bajillion different ways to structure a project. (Almost) All of them make sense to someone. However, the goal of a proper project structure is not to make sense for just one person. The goal is for the project to be intuitively understood by all, easily maintained, and scalable.
When done well, it isn’t necessary to read long articles or documentation on the how and why. There is an intrinsic understanding of where each piece of code fits in the project simply by peering into the folders and reading the filenames. Understanding this rule makes creating asset structures simple and consistent across projects.