Module and theme organization

Module and theme organization

Minnur Yunusov's picture

When you're building a Drupal website it is important to organize your code. Each developer or company has its own way of organizing modules structure. In this blog post I will show the way I organize my code and directory structure.


  • sites/all/modules/contrib - Contains modules downloaded from, Please note, you should never modify any modules in this directory, except for cases when you need to apply patches.
  • sites/all/modules/custom - Contains custom modules.
  • sites/all/modules/features - If you use Features module you create a separate directory, however, you don't have to do this. The "feature" generated with the Features module doesn't look too much different from the module you would write in custom directory. You could write all you code with in the feature in .module file.
  • sites/all/themes/contrib - Contains themes downloaded form the internet.
  • sites/all/themes/custom - Contains custom themes.
  • sites/all/libraries - Contains any 3rd party libraries like wysiwyg editors or javascript plugins.

Organizing settings.php.

In case if you work in a team or your work with contractors you don't want to share credentials to your production environments. In order to prevent this I usually store common configuration settings in setting.php and all the local changes, like DB username/password I keep in the GIT/SVN ignored file called secret.settings.php and I include this file into settings.php.

My sites/default directory structure:

  • settings.php - Default settings.php file, the file includes secret.settings.php and contains all default Drupal settings, I don't store and DB connection information there.
  • example.secret.settings.php - Example file, other developers would need to copy file and rename it to secret.settings.php file and update connection details.
  • secret.settings.php - Contains local settings, like DB connection, ApacheSolr configuration settings, and performance settings. This file is ignored by version control.

Custom module.

My modules usually have the following directory structure:

  • mymodule.module - Main module file, contains all the Drupal hook implementations.
  • - Administrative menu callbacks, add/edit forms.
  • - Public menu callbacks, accessible by non-editor and non-admin users.
  • - Helper functions (e.g call classes from includes/ directory)
  • - Module information file.
  • mymodule.install - Module installer, contains schema information, code cleanup (e.g. remove custom variables in hook_uninstall)
  • includes/ - Contains custom classes, views handlers, etc.
  • templates/ - Theme related files (*.tpl.php files, sometimes I store preprocess files here)
  • plugins/ - I use this directory for custom Ctools plugins
  • css/ - CSS styles
  • images/ - Images and sprite graphics
  • js/ - Javascript helper files


*.info file:

Drupal uses .info files to store metadata about themes and modules. Important information about contents of the file
If you have custom classes, please include all the files using "files" property (example: files[] = tests/example.test). This lets Drupal load your classes only when needed.

Drupal 7 has very useful feature that allows to load CSS/JS files form .info file:

stylesheets[all][] = mymodule_styles.css
scripts[] = mymodule.js

*.module file

Contains all hook implementations.

In order to make code more well organized and load hooks only when needed I use "hook_hook_info()".


The following implementation of hook_hook_info tells Drupal that implementations of hook_node_insert, hook_node_update and hook_node_delete are located in file.

function mymodule_hook_info() {
  $hooks['node_insert'] = array(
    'group' => 'node',
  $hooks['node_update'] = array(
    'group' => 'node',
  $hooks['node_delete'] = array(
    'group' => 'node',
  return $hooks;

By doing this you will reduce the file size of your main module file and load hook_node_* hooks only when needed.

Drupal theme.

When I create a custom theme or theme based on other themes I use the following structure:

  • themes/custom/mytheme/
    • - Theme info file
    • template.php - Theme preprocesses and other helper function
    • favicon.ico - Favicon
    • logo.png - I usually place the main logo out of the images directory
    • images/ - Contains all theme related images
    • css/ - Compiled CSS files
    • less/sass - LESS or SASS files
    • js/ - Various JS helper functions, plugins
    • templates/ - I prefer to create separate folder per template types so it's easier to maintain the theme and locate the file you need to modify
      • views/ - Views related templates, it could also contain subfolder like "views/myview/"
      • nodes/ - Node templates
      • pages/ - Page templates files, page--front.tpl.php, page.tpl.php, etc.
      • blocks/ - Block templates
      • regions/ - Region templates
      • html.tpl.php - Main html wrapper

I would love to hear new ideas and techniques you use in your development process.


Thanks for sharing, Minnur! Looks like "contrib"/"custom" folders become a standard for Drupal files structure. Even Drush supports "contrib" folder for downloading. I also found it useful to create "unstable" folder for patched/forked/sandbox projects.

Post new comment

About Urban Insight

We create elegant, mobile-friendly websites.

We solve complex problems using Drupal and open source software.

Learn More


When inserting special characters in CSS generated content using :before or :after, use hexadecimal notation.

// Like this
a:after {
  content: "\25C2";
// Instead of this
a:after {
  content: "◂";