aboutsummaryrefslogtreecommitdiffstats
path: root/docs/customising
diff options
context:
space:
mode:
authorLouise Crow <louise.crow@gmail.com>2014-06-13 17:20:46 +0100
committerLouise Crow <louise.crow@gmail.com>2014-06-13 17:20:46 +0100
commitb015f34f1fbd9592c5839e5e311136f272df41fa (patch)
treea495330bdd03f8f935d97275ef31b6554d20849c /docs/customising
parent869688c6e1a0fb8c2511a3846107ddedb4c4dea6 (diff)
Move docs content under docs/
Diffstat (limited to 'docs/customising')
-rw-r--r--docs/customising/config.md1172
-rw-r--r--docs/customising/index.md44
-rw-r--r--docs/customising/themes.md191
-rw-r--r--docs/customising/translation.md123
4 files changed, 1530 insertions, 0 deletions
diff --git a/docs/customising/config.md b/docs/customising/config.md
new file mode 100644
index 000000000..2528adefc
--- /dev/null
+++ b/docs/customising/config.md
@@ -0,0 +1,1172 @@
+---
+layout: page
+title: Configuration
+---
+
+# Configuring Alaveteli
+
+<p class="lead">
+ You can control much of how Alaveteli looks and behaves just by
+ changing the config settings.
+</p>
+
+## The general configuration file
+
+The alaveteli code ships with an example configuration file: `config/general.yml-example`.
+
+As part of the [installation process]({{ site.baseurl }}docs/installing ), the
+example file gets copied to `config/general.yml`. You **must** edit this file to
+suit your needs.
+
+Note that the default settings for frontpage examples are designed to work with
+the dummy data shipped with Alaveteli. Once you have real data, you should
+certainly edit these.
+
+Note that there are [other configuration files](#other-config) too, for specific aspects of Alaveteli.
+
+
+## Config settings by topic
+
+The following are all the configuration settings that you can change in `config/general.yml`.
+When you edit this file, remember it must be in the <a href="http://yaml.org">YAML syntax</a>.
+It's not complicated but &mdash; especially if you're editing a list &mdash; be careful to get the
+indentation correct. If in doubt, look at the examples already in the file, and don't use tabs.
+
+
+### Appearance and overall behaviour of the site:
+
+<code><a href="#site_name">SITE_NAME</a></code>
+<br> <code><a href="#domain">DOMAIN</a></code>
+<br> <code><a href="#force_ssl">FORCE_SSL</a></code>
+<br> <code><a href="#force_registration_on_new_request">FORCE_REGISTRATION_ON_NEW_REQUEST</a></code>
+<br> <code><a href="#theme_urls">THEME_URLS</a></code>
+<br> <code><a href="#theme_branch">THEME_BRANCH</a></code>
+<br> <code><a href="#frontpage_publicbody_examples">FRONTPAGE_PUBLICBODY_EXAMPLES</a></code>
+<br> <code><a href="#public_body_statistics_page">PUBLIC_BODY_STATISTICS_PAGE</a></code>
+<br> <code><a href="#minimum_requests_for_statistics">MINIMUM_REQUESTS_FOR_STATISTICS</a></code>
+<br> <code><a href="#responsive_styling">RESPONSIVE_STYLING</a></code>
+
+### Site status:
+
+<code><a href="#read_only">READ_ONLY</a></code>
+<br> <code><a href="#staging_site">STAGING_SITE</a></code>
+
+### Locale and internationalisation:
+
+<code><a href="#iso_country_code">ISO_COUNTRY_CODE</a></code>
+<br> <code><a href="#time_zone">TIME_ZONE</a></code>
+<br> <code><a href="#available_locales">AVAILABLE_LOCALES</a></code>
+<br> <code><a href="#default_locale">DEFAULT_LOCALE</a></code>
+<br> <code><a href="#use_default_browser_language">USE_DEFAULT_BROWSER_LANGUAGE</a></code>
+<br> <code><a href="#include_default_locale_in_urls">INCLUDE_DEFAULT_LOCALE_IN_URLS</a></code>
+
+### Definition of "late":
+
+<code><a href="#reply_late_after_days">REPLY_LATE_AFTER_DAYS</a></code>
+<br> <code><a href="#reply_very_late_after_days">REPLY_VERY_LATE_AFTER_DAYS</a></code>
+<br> <code><a href="#special_reply_very_late_after_days">SPECIAL_REPLY_VERY_LATE_AFTER_DAYS</a></code>
+<br> <code><a href="#working_or_calendar_days">WORKING_OR_CALENDAR_DAYS</a></code>
+
+### Admin access:
+
+<code><a href="#admin_username">ADMIN_USERNAME</a></code>
+<br> <code><a href="#admin_password">ADMIN_PASSWORD</a></code>
+<br> <code><a href="#admin_username">DISABLE_EMERGENCY_USER</a></code>
+<br> <code><a href="#skip_admin_auth">SKIP_ADMIN_AUTH</a></code>
+
+### Email management:
+
+<code><a href="#incoming_email_domain">INCOMING_EMAIL_DOMAIN</a></code>
+<br> <code><a href="#incoming_email_prefix">INCOMING_EMAIL_PREFIX</a></code>
+<br> <code><a href="#incoming_email_secret">INCOMING_EMAIL_SECRET</a></code>
+<br> <code><a href="#blackhole_prefix">BLACKHOLE_PREFIX</a></code>
+<br> <code><a href="#contact_email">CONTACT_EMAIL</a></code>
+<br> <code><a href="#contact_name">CONTACT_NAME</a></code>
+<br> <code><a href="#track_sender_email">TRACK_SENDER_EMAIL</a></code>
+<br> <code><a href="#track_sender_name">TRACK_SENDER_NAME</a></code>
+<br> <code><a href="#raw_emails_location">RAW_EMAILS_LOCATION</a></code>
+<br> <code><a href="#exception_notifications_from">EXCEPTION_NOTIFICATIONS_FROM</a></code>
+<br> <code><a href="#exception_notifications_to">EXCEPTION_NOTIFICATIONS_TO</a></code>
+<br> <code><a href="#forward_nonbounce_responses_to">FORWARD_NONBOUNCE_RESPONSES_TO</a></code>
+<br> <code><a href="#mta_log_path">MTA_LOG_PATH</a></code>
+<br> <code><a href="#mta_log_type">MTA_LOG_TYPE</a></code>
+
+### General admin (keys, paths, back-end services):
+
+<code><a href="#cookie_store_session_secret">COOKIE_STORE_SESSION_SECRET</a></code>
+<br> <code><a href="#recaptcha_public_key">RECAPTCHA_PUBLIC_KEY</a></code>
+<br> <code><a href="#recaptcha_private_key">RECAPTCHA_PRIVATE_KEY</a></code>
+<br> <code><a href="#gaze_url">GAZE_URL</a></code>
+<br> <code><a href="#ga_code">GA_CODE</a></code> (GA=Google Analytics)
+<br> <code><a href="#utility_search_path">UTILITY_SEARCH_PATH</a></code>
+<br> <code><a href="#shared_files_path">SHARED_FILES_PATH</a></code>
+<br> <code><a href="#shared_files">SHARED_FILES</a></code>
+<br> <code><a href="#shared_directories">SHARED_DIRECTORIES</a></code>
+
+### Behaviour settings and switches:
+
+<code><a href="#new_response_reminder_after_days">NEW_RESPONSE_REMINDER_AFTER_DAYS</a></code>
+<br> <code><a href="#max_requests_per_user_per_day">MAX_REQUESTS_PER_USER_PER_DAY</a></code>
+<br> <code><a href="#override_all_public_body_request_emails">OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS</a></code>
+<br> <code><a href="#allow_batch_requests">ALLOW_BATCH_REQUESTS</a></code>
+<br> <code><a href="#public_body_list_fallback_to_default_locale">PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE</a></code>
+<br> <code><a href="#cache_fragments">CACHE_FRAGMENTS</a></code>
+
+### External public services:
+
+<code><a href="#blog_feed">BLOG_FEED</a></code>
+<br> <code><a href="#twitter_username">TWITTER_USERNAME</a></code>
+<br> <code><a href="#twitter_widget_id">TWITTER_WIDGET_ID</a></code>
+<br> <code><a href="#donation_url">DONATION_URL</a></code>
+
+### Development work or special cases:
+
+<code><a href="#debug_record_memory">DEBUG_RECORD_MEMORY</a></code>
+<br> <code><a href="#varnish_host">VARNISH_HOST</a></code>
+<br> <code><a href="#use_mailcatcher_in_development">USE_MAILCATCHER_IN_DEVELOPMENT</a></code>
+<br> <code><a href="#use_ghostscript_compression">USE_GHOSTSCRIPT_COMPRESSION</a></code>
+<br> <code><a href="#html_to_pdf_command">HTML_TO_PDF_COMMAND</a></code>
+
+
+---
+
+## All the general settings
+
+
+<dl class="glossary">
+
+ <dt>
+ <a name="site_name"><code>SITE_NAME</code></a>
+ </dt>
+ <dd>
+ <strong>SITE_NAME</strong> appears in various places throughout the site.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>SITE_NAME: 'Alaveteli'</code>
+ </li>
+ <li>
+ <code>SITE_NAME: 'WhatDoTheyKnow'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="domain"><code>DOMAIN</code></a>
+ </dt>
+ <dd>
+ Domain used in URLs generated by scripts (e.g. for going in some emails)
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>DOMAIN: '127.0.0.1:3000'</code>
+ </li>
+ <li>
+ <code>DOMAIN: 'www.example.com'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="force_ssl"><code>FORCE_SSL</code></a>
+ </dt>
+ <dd>
+ If true forces everyone (in the production environment) to use encrypted connections
+ (via https) by redirecting unencrypted connections. This is <strong>highly
+ recommended</strong> so that logins can't be intercepted by naughty people.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>FORCE_SSL: true</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="iso_country_code"><code>ISO_COUNTRY_CODE</code></a>
+ </dt>
+ <dd>
+ The <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO country code</a>
+ of the country in which your Alaveteli site is deployed.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>ISO_COUNTRY_CODE: GB</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="time_zone"><code>TIME_ZONE</code></a>
+ </dt>
+ <dd>
+ This is the <a href="http://en.wikipedia.org/wiki/List_of_tz_database_time_zones">timezone</a>
+ that Alaveteli usese to display times and dates.
+ If not set, defaults to UTC.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>TIME_ZONE: Australia/Sydney</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="blog_feed"><code>BLOG_FEED</code></a>
+ </dt>
+ <dd>
+ These feeds are displayed accordingly on the Alaveteli "blog" page: <!-- TODO -->
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>BLOG_FEED: 'http://www.mysociety.org/category/projects/whatdotheyknow/feed/'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="twitter_username"><code>TWITTER_USERNAME</code></a>
+ <a name="twitter_widget_id"><code>TWITTER_WIDGET_ID</code></a>
+ </dt>
+ <dd>
+ If you want a twitter feed displayed on the "blog" page, provide the widget ID and username.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>TWITTER_USERNAME: WhatDoTheyKnow</code>
+ </li>
+ <li>
+ <code>TWITTER_WIDGET_ID: '833549204689320031'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="available_locales"><code>AVAILABLE_LOCALES</code></a> &
+ <a name="default_locale"><code>DEFAULT_LOCALE</code></a>
+ </dt>
+ <dd>
+ <strong>AVAILABLE_LOCALES</strong> lists all the locales you want your site to support.
+ If there is more than one, use spaces betwween the entries.
+ Nominate one of these locales as the default with <strong>DEFAULT_LOCALE</strong>.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>AVAILABLE_LOCALES: 'en es'</code>
+ </li>
+ <li>
+ <code>DEFAULT_LOCALE: 'en'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="use_default_browser_language"><code>USE_DEFAULT_BROWSER_LANGUAGE</code></a>
+ </dt>
+ <dd>
+ Should Alaveteli try to use the default language of the user's browser?
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>USE_DEFAULT_BROWSER_LANGUAGE: true</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="include_default_locale_in_urls"><code>INCLUDE_DEFAULT_LOCALE_IN_URLS</code></a>
+ </dt>
+ <dd>
+ Normally, Alaveteli will put the locale into its URLs, like this
+ <code>www.example.com/en/body/list/all</code>. If you don't want this
+ behaviour whenever the locale is the default one, set
+ <strong>INCLUDE_DEFAULT_LOCALE_IN_URLS</strong> to false.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>INCLUDE_DEFAULT_LOCALE_IN_URLS: true</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="reply_late_after_days"><code>REPLY_LATE_AFTER_DAYS</code></a><br>
+ <a name="reply_very_late_after_days"><code>REPLY_VERY_LATE_AFTER_DAYS</code></a><br>
+ <a name="special_reply_very_late_after_days"><code>SPECIAL_REPLY_VERY_LATE_AFTER_DAYS</code></a>
+ <a name="working_or_calendar_days"><code>WORKING_OR_CALENDAR_DAYS</code></a>
+ </dt>
+ <dd>
+ The <strong>REPLY...AFTER_DAYS</strong> settings define how many days must have
+ passed before an answer to a request is officially <em>late</em>.
+ The SPECIAL case is for some types of authority (for example: in the UK, schools) which are
+ granted a bit longer than everyone else to respond to questions.
+ The <strong>WORKING_OR_CALENDAR_DAYS</strong> setting can be either "working" (the default)
+ or "calendar", and determines which days are counted.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>REPLY_LATE_AFTER_DAYS: 20</code>
+ </li>
+ <li>
+ <code>REPLY_VERY_LATE_AFTER_DAYS: 40</code>
+ </li>
+ <li>
+ <code>SPECIAL_REPLY_VERY_LATE_AFTER_DAYS: 60</code>
+ </li>
+ <li>
+ <code>WORKING_OR_CALENDAR_DAYS: working</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="frontpage_publicbody_examples"><code>FRONTPAGE_PUBLICBODY_EXAMPLES</code></a>
+ </dt>
+ <dd>
+ Specify which public bodies you want to be listed as examples on the home page,
+ using their <code>short_names</code>.
+ If you want more than one, separate them with semicolons.
+ Comment this out if you want this to be auto-generated.
+ <p>
+ <strong>Warning</strong>: this is slow &mdash; don't use in production!
+ </p>
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>FRONTPAGE_PUBLICBODY_EXAMPLES: 'tgq'</code>
+ </li>
+ <li>
+ <code>FRONTPAGE_PUBLICBODY_EXAMPLES: 'tgq;foo;bar'</code>
+ </li>
+ <li>
+ <code># FRONTPAGE_PUBLICBODY_EXAMPLES: </code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="theme_urls"><code>THEME_URLS</code></a>
+ </dt>
+ <dd>
+ URLs of <a href="{{ site.baseurl }}docs/customising/themes">themes</a> to download and use
+ (when running the <code>rails-post-deploy</code> script). The earlier in the list means
+ the templates have a higher priority.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <pre>
+THEME_URLS:
+ - 'git://github.com/mysociety/alavetelitheme.git'
+</pre>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="theme_branch"><code>THEME_BRANCH</code></a>
+ </dt>
+ <dd>
+ When <code>rails-post-deploy</code> installs the <a href="{{ site.baseurl }}docs/customising/themes">themes</a>,
+ it will try the theme branch first, but only if you've set <code>THEME_BRANCH</code>
+ to be true. If the branch doesn't exist it will fall back to using a tagged version
+ specific to your installed alaveteli version, and if that doesn't exist it will
+ back to <code>master</code>.
+ <p>
+ The default theme is the "Alaveteli" theme. This gets installed automatically when
+ <code>rails-post-deploy</code> runs.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>THEME_BRANCH: false</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="force_registration_on_new_request"><code>FORCE_REGISTRATION_ON_NEW_REQUEST</code></a>
+ </dt>
+ <dd>
+ Does a user needs to sign in to start the New Request process?
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>FORCE_REGISTRATION_ON_NEW_REQUEST: false</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="incoming_email_domain"><code>INCOMING_EMAIL_DOMAIN</code></a>
+ </dt>
+ <dd>
+ Your email domain for incoming mail.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>INCOMING_EMAIL_DOMAIN: 'localhost'</code>
+ </li>
+ <li>
+ <code>INCOMING_EMAIL_DOMAIN: 'foifa.com'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="incoming_email_prefix"><code>INCOMING_EMAIL_PREFIX</code></a>
+ </dt>
+ <dd>
+ An optional prefix to help you distinguish FOI requests.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>INCOMING_EMAIL_PREFIX: ''</code>
+ </li>
+ <li>
+ <code>INCOMING_EMAIL_PREFIX: 'foi+'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="incoming_email_secret"><code>INCOMING_EMAIL_SECRET</code></a>
+ </dt>
+ <dd>
+ Used for hash in request email address.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>INCOMING_EMAIL_SECRET: '11ae 4e3b 70ff c001 3682 4a51 e86d ef5f'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="blackhole_prefix"><code>BLACKHOLE_PREFIX</code></a>
+ </dt>
+ <dd>
+ Used as envelope from at the incoming email domain for cases where you don't care about failure.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>BLACKHOLE_PREFIX: 'do-not-reply-to-this-address'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="admin_username"><code>ADMIN_USERNAME</code></a>
+ &amp;
+ <a name="admin_password"><code>ADMIN_PASSWORD</code></a>
+ <br>
+ <a name="admin_username"><code>DISABLE_EMERGENCY_USER</code></a>
+ </dt>
+ <dd>
+ The emergency user.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>ADMIN_USERNAME: 'adminxxxx'</code>
+ </li>
+ <li>
+ <code>ADMIN_PASSWORD: 'passwordx'</code>
+ </li>
+ <li>
+ <code>DISABLE_EMERGENCY_USER: false</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="skip_admin_auth"><code>SKIP_ADMIN_AUTH</code></a>
+ </dt>
+ <dd>
+ Set this to true, and the admin interface will be available to anonymous users.
+ Obviously, you should not set this to be true in production environments.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>SKIP_ADMIN_AUTH: false</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="contact_email"><code>CONTACT_EMAIL</code></a>
+ &amp;
+ <a name="contact_name"><code>CONTACT_NAME</code></a>
+ </dt>
+ <dd>
+ Email "from" details.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>CONTACT_EMAIL: 'team@example.com'</code>
+ </li>
+ <li>
+ <code>CONTACT_NAME: 'Alaveteli Webmaster'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="track_sender_email"><code>TRACK_SENDER_EMAIL</code></a> &amp;
+ <a name="track_sender_name"><code>TRACK_SENDER_NAME</code></a>
+ </dt>
+ <dd>
+ Email "from" details for track messages.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>TRACK_SENDER_EMAIL: 'alaveteli@example.com'</code>
+ </li>
+ <li>
+ <code>TRACK_SENDER_NAME: 'Alaveteli Webmaster'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="raw_emails_location"><code>RAW_EMAILS_LOCATION</code></a>
+ </dt>
+ <dd>
+ Where the raw incoming email data gets stored.
+ <strong>Make sure you back this up!</strong>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>RAW_EMAILS_LOCATION: 'files/raw_emails'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="cookie_store_session_secret"><code>COOKIE_STORE_SESSION_SECRET</code></a>
+ </dt>
+ <dd>
+ Secret key for signing cookie_store sessions. Make it long and random.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>COOKIE_STORE_SESSION_SECRET: 'uIngVC238Jn9NsaQizMNf89pliYmDBFugPjHS2JJmzOp8'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="read_only"><code>READ_ONLY</code></a>
+ </dt>
+ <dd>
+ If present, <strong>READ_ONLY</strong> puts the site in read-only mode,
+ and uses the text as reason (whole paragraph). Please use a read-only database
+ user as well, as it only checks in a few obvious places.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ Typically, you do <strong>not</strong> want to run your site in
+ read-only mode &mdash; so set <strong>READ_ONLY</strong> to be
+ an empty string.
+ <br>
+ <code>
+ READ_ONLY: ''
+ </code>
+ </li>
+ <li>
+ <code>
+ READ_ONLY: 'The site is not currently accepting requests while we move the server.'
+ </code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="staging_site"><code>STAGING_SITE</code></a>
+ </dt>
+ <dd>
+ Is this a
+ <a href="{{site.baseurl}}docs/glossary/#staging" class="glossary">staging</a> or
+ <a href="{{site.baseurl}}docs/glossary/#development" class="glossary">development</a> site?
+ If not, it's a live <a href="{{site.baseurl}}docs/glossary/#production" class="glossary">production</a>
+ site. This setting controls whether or not the <code>rails-post-deploy</code>
+ script will create the file <code>config/rails_env.rb</code> file to force
+ Rails into production environment.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ For staging or development:
+ <p>
+ <code>STAGING_SITE: 1</code>
+ </p>
+ </li>
+ <li>
+ For production:
+ <p>
+ <code>STAGING_SITE: 0</code>
+ </p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="recaptcha_public_key"><code>RECAPTCHA_PUBLIC_KEY</code></a> &amp;
+ <a name="recaptcha_private_key"><code>RECAPTCHA_PRIVATE_KEY</code></a>
+ </dt>
+ <dd>
+ Recaptcha, for detecting humans. Get keys here:
+ <a href="http://recaptcha.net/whyrecaptcha.html">http://recaptcha.net/whyrecaptcha.html</a>
+
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>RECAPTCHA_PUBLIC_KEY: '7HoPjGBBBBBBBBBkmj78HF9PjjaisQ893'</code>
+ </li>
+ <li>
+ <code>RECAPTCHA_PRIVATE_KEY: '7HjPjGBBBBBCBBBpuTy8a33sgnGG7A'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="new_response_reminder_after_days"><code>NEW_RESPONSE_REMINDER_AFTER_DAYS</code></a>
+ </dt>
+ <dd>
+ Number of days after which to send a 'new response reminder'.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>NEW_RESPONSE_REMINDER_AFTER_DAYS: [3, 10, 24]</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="debug_record_memory"><code>DEBUG_RECORD_MEMORY</code></a>
+ </dt>
+ <dd>
+ For debugging memory problems. If true, Alaveteli logs
+ the memory use increase of the Ruby process due to the
+ request (Linux only). Since Ruby never returns memory to the OS, if the
+ existing process previously served a larger request, this won't
+ show any consumption for the later request.
+
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>DEBUG_RECORD_MEMORY: false</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="use_ghostscript_compression"><code>USE_GHOSTSCRIPT_COMPRESSION</code></a>
+ </dt>
+ <dd>
+ Currently we default to using pdftk to compress PDFs. You can
+ optionally try Ghostscript, which should do a better job of
+ compression. Some versions of pdftk are buggy with respect to
+ compression, in which case Alaveteli doesn't recompress the PDFs at
+ all and logs a warning message "Unable to compress PDF" &mdash; which would
+ be another reason to try this setting.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>USE_GHOSTSCRIPT_COMPRESSION: true</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="gaze_url"><code>GAZE_URL</code></a>
+ </dt>
+ <dd>
+ Alateveli uses mySociety's gazeteer service to determine country from incoming
+ IP address (this lets us suggest an Alaveteli in their country, if one exists).
+ You shouldn't normally need to change this.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>GAZE_URL: http://gaze.mysociety.org</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="forward_nonbounce_responses_to"><code>FORWARD_NONBOUNCE_RESPONSES_TO</code></a>
+ </dt>
+ <dd>
+ The email address to which non-bounce responses should be forwarded
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>FORWARD_NONBOUNCE_RESPONSES_TO: user-support@example.com</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="html_to_pdf_command"><code>HTML_TO_PDF_COMMAND</code></a>
+ </dt>
+ <dd>
+ Path to a program that converts an HTML page in a file to PDF. It
+ should take two arguments: the URL, and a path to an output file.
+ A static binary of <a href="http://wkhtmltopdf.org">wkhtmltopdf</a> is recommended.
+ If the command is not present, a text-only version will be rendered
+ instead.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>HTML_TO_PDF_COMMAND: /usr/local/bin/wkhtmltopdf-amd64</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="exception_notifications_from"><code>EXCEPTION_NOTIFICATIONS_FROM</code></a> &amp;
+ <a name="exception_notifications_to"><code>EXCEPTION_NOTIFICATIONS_TO</code></a>
+ </dt>
+ <dd>
+ Email address(es) used for sending exception notifications.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <pre>
+EXCEPTION_NOTIFICATIONS_FROM: do-not-reply-to-this-address@example.com
+
+EXCEPTION_NOTIFICATIONS_TO:
+ - robin@example.com
+ - seb@example.com
+</pre>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="max_requests_per_user_per_day"><code>MAX_REQUESTS_PER_USER_PER_DAY</code></a>
+ </dt>
+ <dd>
+ This rate limiting can be turned off per-user via the admin interface.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>MAX_REQUESTS_PER_USER_PER_DAY: 6</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="varnish_host"><code>VARNISH_HOST</code></a>
+ </dt>
+ <dd>
+ If you're running behind Varnish, it might help to set this to
+ work out where to send purge requests.
+ Otherwise, don't set it.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>VARNISH_HOST: null</code>
+ </li>
+ <li>
+ <code>VARNISH_HOST: localhost</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="ga_code"><code>GA_CODE</code> (GA=Google Analytics)</a>
+ </dt>
+ <dd>
+ Adding a value here will enable Google Analytics on all non-admin pages for non-admin users.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>GA_CODE: ''</code>
+ </li>
+ <li>
+ <code>GA_CODE: 'AB-8222142-14'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="override_all_public_body_request_emails"><code>OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS</code></a>
+ </dt>
+ <dd>
+ If you want to override <strong>all</strong> the public body request emails with
+ your own email address so that request emails that would normally go to the public body
+ go to you, use this setting.
+ This is useful for a staging server, so you can play with the whole process of sending requests
+ without inadvertently sending an email to a real authority.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS: test-email@foo.com</code>
+ </li>
+ <li>
+ If you don't want this behaviour, comment the setting out
+ <br>
+ <code># OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS:</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="utility_search_path"><code>UTILITY_SEARCH_PATH</code></a>
+ </dt>
+ <dd>
+ Search path for external command-line utilities (such as pdftohtml, pdftk, unrtf).
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>UTILITY_SEARCH_PATH: ["/usr/bin", "/usr/local/bin"]</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="mta_log_path"><code>MTA_LOG_PATH</code></a>
+ </dt>
+ <dd>
+ Path to your exim or postfix log files that will get sucked up
+ by <code>script/load-mail-server-logs</code>.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>MTA_LOG_PATH: '/var/log/exim4/exim-mainlog-*'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="mta_log_type"><code>MTA_LOG_TYPE</code></a>
+ </dt>
+ <dd>
+ Are you using "exim" or "postfix" for your Mail Transfer Agnt (MTA)?
+
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>MTA_LOG_TYPE: "exim"</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="donation_url"><code>DONATION_URL</code></a>
+ </dt>
+ <dd>
+ URL where people can donate to the organisation running the site. If set,
+ this will be included in the message people see when their request is
+ successful.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>DONATION_URL: "http://www.mysociety.org/donate/"</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="public_body_statistics_page"><code>PUBLIC_BODY_STATISTICS_PAGE</code></a> &amp;
+ <a name="minimum_requests_for_statistics"><code>MINIMUM_REQUESTS_FOR_STATISTICS</code></a>
+ </dt>
+ <dd>
+ If <strong>PUBLIC_BODY_STATISTICS_PAGE</strong> is set to true, Alaveteli will make a
+ page of statistics on the performance of public bodies (which you can see at
+ <code>/body_statistics</code>).
+ The page will only consider public bodies that have had at least the number of requests
+ set by <strong>MINIMUM_REQUESTS_FOR_STATISTICS</strong>.
+
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>PUBLIC_BODY_STATISTICS_PAGE: false</code>
+ </li>
+ <li>
+ <code>MINIMUM_REQUESTS_FOR_STATISTICS: 50</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="public_body_list_fallback_to_default_locale"><code>PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE</code></a>
+ </dt>
+ <dd>
+ If you would like the public body list page to include bodies that have no translation
+ in the current locale (but which do have a translation in the default locale), set this to true.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE: false</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="use_mailcatcher_in_development"><code>USE_MAILCATCHER_IN_DEVELOPMENT</code></a>
+ </dt>
+ <dd>
+ <!-- TODO check mailcatcher URL -->
+ If true, while in development mode, try to send mail by SMTP to port
+ 1025 (the port the <a href="http://mailcatcher.me">mailcatcher</a> listens on by default):
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>USE_MAILCATCHER_IN_DEVELOPMENT: true</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="cache_fragments"><code>CACHE_FRAGMENTS</code></a>
+ </dt>
+ <dd>
+ Use memcached to cache HTML fragments for better performance.
+ This will only have an effect in environments where
+ <code>config.action_controller.perform_caching</code> is set to true
+
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>CACHE_FRAGMENTS: true</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+
+ <dt>
+ <a name="shared_files_path"><code>SHARED_FILES_PATH</code></a>
+ </dt>
+ <dd>
+ In some deployments of Alaveteli you may wish to install each newly
+ deployed version alongside the previous ones, in which case certain
+ files and resources should be shared between these installations.
+ For example, the <code>files</code> directory, the <code>cache</code> directory and the
+ generated graphs such as <code>public/foi-live-creation.png</code>. If you're
+ installing Alaveteli in such a setup then set <strong>SHARED_FILES_PATH</strong> to
+ the directory you're keeping these files under. Otherwise, leave it blank.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>SHARED_FILES_PATH: ''</code> <!-- TODO specific example -->
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+
+ <dt>
+ <a name="shared_files"><code>SHARED_FILES</code></a> &
+ <a name="shared_directories"><code>SHARED_DIRECTORIES</code></a>
+ </dt>
+ <dd>
+ If you have <strong>SHARED_FILES_PATH</strong> set, then these options list the files
+ and directories that are shared; i.e. those to which the deploy scripts
+ should create symlinks from the repository.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <pre>
+SHARED_FILES:
+ - config/database.yml
+ - config/general.yml
+ - config/rails_env.rb
+ - config/newrelic.yml
+ - config/httpd.conf
+ - public/foi-live-creation.png
+ - public/foi-user-use.png
+ - config/aliases
+ </pre>
+ </li>
+ <li>
+ <pre>
+SHARED_DIRECTORIES:
+ - files/
+ - cache/
+ - lib/acts_as_xapian/xapiandbs/
+ - vendor/bundle
+ - public/assets
+ </pre>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="allow_batch_requests"><code>ALLOW_BATCH_REQUESTS</code></a>
+ </dt>
+ <dd>
+ Allow some users to make batch requests to multiple authorities. Once
+ this is set to true, you can enable batch requests for an individual
+ user via the user admin page.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>ALLOW_BATCH_REQUESTS: false</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="responsive_styling"><code>RESPONSIVE_STYLING</code></a>
+ </dt>
+ <dd>
+
+ Use the responsive base stylesheets and templates, rather than
+ those that only render the site at a fixed width. These
+ stylesheets are currently experimental but will become the default
+ in the future. They allow the site to render nicely on mobile
+ devices as well as larger screens. Currently the fixed width
+ stylesheets are used by default.
+
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>RESPONSIVE_STYLING: true</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+</dl>
+
+<a name="other-config"> </a>
+
+## Other configuration files
+
+Note that there are other configuration files for Alaveteli &mdash; you'll find them all
+in the `config` directory. These are presented in the git repository as `*-example` files
+which you can copy into place.
+
+<dl>
+ <dt>
+ <strong>database.yml</strong>
+ </dt>
+ <dd>
+ database settings (as per Rails)
+ </dd>
+ <dt>
+ <strong>deploy.yml</strong>
+ </dt>
+ <dd>
+ deployment specifications used by Capistrano
+ </dd>
+ <dt>
+ <strong>httpd.conf, nginx.conf</strong>
+ </dt>
+ <dd>
+ Apache and Nginx configuration suggestions
+ </dd>
+ <dt>
+ <strong>newrelic.yml</strong>
+ </dt>
+ <dd>
+ Analytics configuration
+ </dd>
+</dl>
diff --git a/docs/customising/index.md b/docs/customising/index.md
new file mode 100644
index 000000000..4b8cf9fda
--- /dev/null
+++ b/docs/customising/index.md
@@ -0,0 +1,44 @@
+---
+layout: page
+title: Customising
+---
+
+# Customising Alaveteli
+
+<p class="lead">
+ There are two ways to make your installation look and act the way you want.
+ Some behaviour can be controlled with <strong>configuration settings</strong>.
+ For more complex changes, you'll need to create a new <strong>theme</strong>.
+</p>
+
+
+## Configuration settings
+
+You can customise much of Alaveteli's behaviour just by editing the configuration
+file. This [complete list of Alaveteli's config settings]({{ site.baseurl }}docs/customising/config)
+shows the sort of things you can control in this way.
+
+<!-- TODO key settings -->
+
+## Simple branding: colour and logo
+
+It's common to want to change the basic appearance of the site. Although you
+can simply edit the default templates and CSS to do this, we **strongly
+recommend** that you [create a theme]({{ site.baseurl }}docs/customising/themes).
+
+Themes do not need to be especially complex, but they allow your changes to
+work alongside the core code, which you can then update (when new releases or
+updates become available).
+
+## Need Alaveteli in a different language?
+
+No problem! See the [information about translating Alaveteli]({{ site.baseurl }}docs/customising/translation).
+
+## Complex changes
+
+If you are a developer (or you have a team of programmers available) you can
+add any customisation that you want. But it's important to do this without
+breaking the core code, so that you can accept new releases with updates.
+There's more detail in the [page about themes]({{ site.baseurl }}docs/customising/themes).
+
+See also the [documentation for developers]({{ site.baseurl }}docs/developers).
diff --git a/docs/customising/themes.md b/docs/customising/themes.md
new file mode 100644
index 000000000..65410ece2
--- /dev/null
+++ b/docs/customising/themes.md
@@ -0,0 +1,191 @@
+---
+layout: page
+title: Themes
+---
+
+# Alaveteli's themes
+
+<p class="lead">
+ Alaveteli uses <strong>themes</strong> to make the site look and run
+ differently from the default.
+ Simple changes like colour and logo are relatively easy, but themes can also
+ control more complex things like <em>how</em> the site behaves.
+</p>
+
+When you customise your Alaveteli site, there is a lot you can change just
+by editing the [config settings]({{ site.baseurl }}docs/customising/config).
+But if you want to change the way the site looks, or add more specific
+behaviour, you'll need to make a **theme**.
+
+You don't need to be a programmer in order to make simple changes, but you will
+need to be confident enough to copy and change some files. If you're not sure
+about this, [ask for help](/community)!
+
+## What you might want to change
+
+The most common requirement is to brand the site: at a minimum,
+[inserting your own logo](#changing-the-logo) and [colour scheme](#changing-the-colour-scheme). You may also want to tweak
+the different states that a request can go through. You'll also want
+to edit the categories that public bodies can appear in (i.e. the
+groupings on the left hand side of the
+"[View authorities](http://www.whatdotheyknow.com/body/list/all)" page
+on WhatDoTheyKnow.
+
+There may also be other things you want to customise -- drop a line on
+the developer's mailing list to discuss what you need. We're still working
+out the best way of doing these kinds of customisations!
+
+In any case, the important principle to bear in mind is that the less
+you override and customise the code, the easier your site will be to
+maintain in the long term. Any customisation is possible, but for
+each customisation beyond the simple cases documented here, ask
+yourself (or your client), "can we possibly live without this?" If the
+answer is "no", then consider starting a discussion about a pluggable
+way of achieving your goals, rather than overriding any of the core
+code.
+
+## General principles
+
+We try to encapsulate all site-specific functionality in one of these
+places:
+
+* Site [configuration]({{ site.baseurl }}docs/customising/config)
+ (e.g., the name of your site, the available
+ languages, and so on &mdash; all in `config/general.yml`)
+* Data (e.g. the public bodies to whom requests should be addressed)
+* A theme, installed in `lib/themes`.
+
+This document is about what you can do in a theme.
+
+By default, the sample theme ("alavetelitheme") has already been
+installed. See the setting
+[`THEME_URLS`]({{ site.baseurl }}docs/customising/config/#theme_urls)
+in `general.yml` for an explanation.
+
+You can also install the sample theme by hand, by running:
+
+ bundle exec rake themes:install
+
+The sample theme contains examples for nearly everything you might
+want to customise. You should probably make a copy, rename it, and
+use that as the basis for your own theme.
+
+## Make sure your theme is as lightweight as possible
+
+The more you put in your theme, the harder it will be to upgrade to
+future versions of Alaveteli. Everything you place in your theme
+overrides things in the core theme, so if you make a new "main
+template", then new widgets that appear in the core theme won't appear
+on your website.
+
+Therefore, you should consider how you can brand your website without
+changing much in the core theme. The ideal would be if you are able
+to rebrand the site by only changing the CSS. You will also need to
+add custom help pages, as described below.
+
+## Branding the site
+
+The core templates that comprise the layout and user interface of an
+Alaveteli site live in `app/views/`. They use Rails' ERB syntax.
+For example, the template for the home page lives at
+`app/views/general/frontpage.html.erb`, and the template for the "about
+us" page is at `app/views/help/about.html.erb`.
+
+Obviously, you *could* edit those core files directly, but this would
+be a Bad Idea, because you would find it increasingly hard to do
+upgrades. Having said that, sometimes you may want to change the core
+templates in a way that would benefit everyone, in which case, discuss
+the changes on the mailing list, make them in a fork of Alaveteli, and
+then issue a pull request.
+
+Normally, however, you should override these pages **in your own
+theme**, by placing them at a corresponding location within your
+theme's `lib/` directory. These means that a file at
+`lib/themes/alavetelitheme/lib/views/help/about.rhml` will appear
+instead of the core "about us" file.
+
+### Changing the logo
+
+Alaveteli uses Rails' [asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html) to convert and compress stylesheets written in
+<a href="{{ site.baseurl }}docs/glossary/#sass" class="glossary">Sass</a>,
+the css extension language, to minified concatenated css. Assets are stored in core Alaveteli under `app/assets` - in `fonts`, `images`, `javascripts` and `stylesheets`.
+The default theme has corresponding asset directories in `alavetelitheme/assets` Asset files placed in these directories will override those in the core directories. As with templates, a file at `lib/themes/alavetelitheme/assets/images/logo.png` will appear on the site instead of the logo from `app/assets/images/logo.png`.
+
+### Changing the colour scheme
+
+Alaveteli uses a set of basic
+<a href="{{ site.baseurl }}docs/glossary/#sass" class="glossary">Sass</a>
+modules to define the layout for the site on different device sizes, and some basic styling. These modules are in `app/assets/stylesheets/responsive`. The colours and fonts are added in the theme - alavetelitheme defines them in `lib/themes/alavetelitheme/assets/stylesheets/responsive/custom.scss`. Colours used in the theme are defined as variables at the top of this file and you can edit them here.
+
+### Changing other styling
+
+To change other styling, you can add to or edit the styles in `lib/themes/alavetelitheme/assets/stylesheets/responsive/custom.scss`. Styles defined here will override those in the sass modules in `app/assets/stylesheets/responsive` as they will be imported last by `app/assets/stylesheets/responsive/all.scss`. However, if you want to substantially change the way a particular part of the site is laid out, you may want to override one of the core sass modules. You could override the layout of the front page, for example, by copying `app/assets/stylesheets/responsive/_frontpage_layout.scss` to `lib/themes/alavetelitheme/assets/stylesheets/responsive/_frontpage_layout.scss` and editing it.
+
+You can load extra stylesheets and javascript files by adding them to `lib/themes/alavetelitheme/lib/views/general/_before_head_end.html.erb`
+
+## Adding your own categories for public bodies
+
+Categories are implemented in Alaveteli using tags. Specific tags can
+be designated to group authorities together as a category.
+
+There's a file in the sample theme,
+`alavetelitheme/lib/public_body_categories_en.rb`, which contains a
+nested structure that defines categories. It contains a comment
+describing its structure. You should make a copy of this file for each
+locale you support.
+
+## Customising the request states
+
+As mentioned above, if you can possibly live with the
+[default Alaveteli request statuses]({{ site.baseurl }}docs/running/states),
+it would be good to do so. Note that you can set how many days counts
+as "overdue" in the main site config file &mdash;
+see [`REPLY_LATE_AFTER_DAYS`]({{ site.baseurl }}docs/customising/config/#reply_late_after_days).
+
+If you can't live with the states as they are, there's a very basic
+way to add to them (which will get improved over time). There's not
+currently a way to remove any easily. There is an example of how to
+do this in the `alavetelitheme`.
+
+To do add states, create two modules in your theme,
+`InfoRequestCustomStates` and `RequestControllerCustomStates`. The
+former must have these methods:
+
+* `theme_calculate_status`: return a tag to identify the current state of the request
+* `theme_extra_states`: return a list of tags which identify the extra states you'd like to support
+* `theme_display_status`: return human-readable strings corresponding with these tags
+
+The latter must have one method:
+
+* `theme_describe_state`: Return a notice for the user suitable for
+ displaying after they've categorised a request; and redirect them to
+ a suitable next page
+
+When you've added your extra states, you also need to create the following files in your theme:
+
+* `lib/views/general/_custom_state_descriptions.html.erb`: Descriptions
+ of your new states, suitable for displaying to end users
+* `lib/views/general/_custom_state_transitions_complete.html.erb`:
+ Descriptions for any new states that you might characterise as
+ 'completion' states, for displaying on the categorisation form that
+ we ask requestors to fill out
+* `lib/views/general/_custom_state_transitions_pending.html.erb`: As
+ above, but for new states you might characterise as 'pending'
+ states.
+
+You can see examples of these customisations in
+[this commit](https://github.com/sebbacon/informatazyrtare-theme/commit/2b240491237bd72415990399904361ce9bfa431d)
+for the Kosovan version of Alaveteli, Informata Zyrtare (ignore the
+file `lib/views/general/_custom_state_transitions.html.erb`, which is
+unused).
+
+## Adding new pages in the navigation
+
+`alavetelitheme/lib/config/custom-routes.rb` allows you to extend the base routes in
+Alaveteli. The example in `alavetelitheme` adds an extra help page.
+You can also use this to override the behaviour of specific pages if
+necessary.
+
+## Adding or overriding models and controllers
+
+If you need to extend the behaviour of Alaveteli at the controller or model level, see `alavetelitheme/lib/controller_patches.rb` and `alavetelitheme/lib/model_patches.rb` for examples.
diff --git a/docs/customising/translation.md b/docs/customising/translation.md
new file mode 100644
index 000000000..4f3c39270
--- /dev/null
+++ b/docs/customising/translation.md
@@ -0,0 +1,123 @@
+---
+layout: page
+title: Translation
+---
+
+# Translating Alaveteli
+
+<p class="lead">
+ We've designed Alaveteli to be used in many different
+ jurisdictions all around the world. If it doesn't already
+ support the language you need, you can help by translating
+ it. This page explains how.
+</p>
+
+## Alaveteli's translations
+
+The software translations are implemented using GNU gettext, and the resource
+files are managed in Transifex.
+
+The Transifex project is at
+[https://www.transifex.net/projects/p/alaveteli](https://www.transifex.net/proje
+cts/p/alaveteli) -- you'll probably want an account there (ask on the mailing
+list). It has a fairly easy-to-use interface for contributing translations.
+
+There are three roles in the translation process, and each one is described
+below: **translator**, **developer**, and **release manager**. You probably only
+need to know about the one that applies to you.
+
+## Translation process: translator's view
+
+**If you're just working on translating Alaveteli into a language you know, then
+this section is for you.**
+
+When a developer adds a new feature to the user interface in Alaveteli, they
+use some code to mark sentences or words ("strings") that they think will need
+to be translated.
+
+When the Alaveteli release manager is planning a release, they will upload a
+template containing all the strings to be translated (called a POT) to
+Transifex. This causes your own translations in Transifex to be updated with
+the latest strings.
+
+When you visit Transifex, it will prompt you to fill out values for all new
+strings, and all strings that have been modified. In the case where a string
+has only been slightly modified, such as with punctuation ("Hello" has become
+"Hello!"), Transifex will suggest a suitable translation for you (look for the
+"suggestions" tab under the source string).
+
+In order for this feature to work properly, the release manager has to download
+your translations, run a program that inserts the suggestions, and then upload
+them again. Therefore, when a release candidate is announced, make sure you
+have uploaded any outstanding translations, or you will lose them.
+
+When a release candidate has been annouced, there is a **translation freeze**:
+during this period, developers must not add any new strings to the software, so
+you can be confident that you're translating everything that will be in the
+final release.
+
+The release manager will also give you a **translation deadline**. After this
+date, you can continue to contribute new translations, but they won't make it
+into the release.
+
+### General notes on translation in Transifex
+
+Some strings will have comments attached to them from the Alaveteli
+application developers about the context in which the text appears in the
+application — these comments will appear under the 'Details' tab for the text
+in Transifex.
+
+Some strings will have **placeholders** in them to indicate that Alaveteli
+will insert some text of its own into them when they're displayed. They
+will be surrounded by double curly brackets, and look like this:
+
+<code>
+ some text with &#123;&#123;placeholder&#125;&#125; in it
+</code>
+
+For these strings, don't translate the placeholder. It needs to stay exactly
+the same for the text to be inserted properly:
+
+<code>
+ ein Text mit &#123;&#123;placeholder&#125;&#125; in ihm
+</code>
+
+Similarly, some strings may contain small bits of HTML — these will have
+code in angle brackets (it might really be indicating that the text is a link,
+or that it needs special formatting). For example:
+
+<code>
+ please &lt;a href=\"&#123;&#123;url&#125;&#125;\"&gt;send it to us&lt;/a&gt;
+</code>
+
+Again, don't edit the bits between the angle brackets — preserve them in your
+translation, and just edit the text around them. So the example might become:
+
+<code>
+ bitte &lt;a href=\"&#123;&#123;url&#125;&#125;\"&gt;schicken Sie es uns&lt;/a&gt;
+</code>
+
+Some strings are in the form of two pieces of text separated by a vertical
+bar (`|`) character, e.g. `IncomingMessage|Subject`. These represent attribute
+names, so `IncomingMessage|Subject` is the subject attribute of an incoming
+message on the site. Do not prioritise these types of text when translating --
+they do not appear on the site anywhere at the moment, and when they do, they
+will only be used in the admin interface. If you do translate them, only
+translate the text that comes *after* the `|`.
+
+## Translation process: developers' view
+
+**If you're writing new code for Alaveteli, then you're a developer, and you
+need to understand how to make any text you add easy for translators to work
+with.**
+
+Please read our [internationalisation
+guide](http://mysociety.github.io/internationalization.html) for our advice on
+using strings that will need translation. This applies across all mySociety
+projects, not just Alaveteli.
+
+The release manager will enforce a translation freeze just before a new release
+is cut. During such time, you must not introduce new strings to the code if
+your work is due for inclusion in this release. This is necessary to allow
+translators time to complete and check their translations against all the known
+strings.