aboutsummaryrefslogtreecommitdiffstats
path: root/docs/customising
diff options
context:
space:
mode:
Diffstat (limited to 'docs/customising')
-rw-r--r--docs/customising/boundaries.md459
-rw-r--r--docs/customising/checklist.md206
-rw-r--r--docs/customising/cobrand-module.md105
-rw-r--r--docs/customising/config.md1122
-rw-r--r--docs/customising/css.md322
-rw-r--r--docs/customising/fms_and_mapit.md63
-rw-r--r--docs/customising/geocoder.md35
-rw-r--r--docs/customising/index.md82
-rw-r--r--docs/customising/integration.md228
-rw-r--r--docs/customising/language/index.md140
-rw-r--r--docs/customising/language/technical.md38
-rw-r--r--docs/customising/login.md41
-rw-r--r--docs/customising/logo.md29
-rw-r--r--docs/customising/send_reports.md83
-rw-r--r--docs/customising/static-pages.md35
-rw-r--r--docs/customising/templates.md113
16 files changed, 3101 insertions, 0 deletions
diff --git a/docs/customising/boundaries.md b/docs/customising/boundaries.md
new file mode 100644
index 000000000..d48a472aa
--- /dev/null
+++ b/docs/customising/boundaries.md
@@ -0,0 +1,459 @@
+---
+layout: page
+title: Admin boundaries
+---
+
+# Admin boundaries and FixMyStreet
+
+<p class="lead">
+ When you set up FixMyStreet, you usually need to provide <strong>admin boundaries</strong>
+ for each of the
+ <a href="{{ "/glossary/#body" | relative_url }}" class="glossary__link">bodies</a>
+ you'll be sending reports to. If you're lucky, the boundaries might already
+ be available. If not, you'll have to make them. This page explains your
+ options.
+</p>
+
+## Why FixMyStreet needs boundaries
+
+When someone sticks a pin in the map to report a problem, FixMyStreet uses
+boundaries to answer the question: _who is responsible for fixing problems
+**here**_?
+
+This also means that boundaries can be used to determine if the pin has
+been put somewhere that is *not* covered by any bodies.
+
+<div class="attention-box">
+ We've written a separate page about
+ <a href="{{ "/customising/fms_and_mapit/" | relative_url }}">how FixMyStreet uses MapIt</a>,
+ which is the service that determines which area any point (pin) is within. It's
+ helpful to understand how that works &mdash; because it also explains how
+ FixMyStreet determines which categories of problem can be reported at any
+ location &mdash; but the rest of this page is about making and using the boundaries that
+ FixMyStreet needs.
+</div>
+
+FixMyStreet finds all the bodies that are associated with the area (or areas)
+that the pin is inside -- those are the bodies to whom the report might be sent.
+Which of these bodies is actually chosen depends on the
+<a href="{{ "/glossary/#category" | relative_url }}" class="glossary__link">category</a>
+the user selects when they complete their problem report.
+
+## Boundaries are independent of your maps!
+
+**Boundaries are not really anything to do with maps** &mdash; they exist
+independently of the maps you're using (although, of course, both are about
+geography). FixMyStreet shows the map *before* the user clicks on it to place
+the pin. It doesn't check the boundaries until *after* the pin has been placed.
+
+## Every body must be associated with an area
+
+So if you're setting up FixMyStreet to run in your region, you *must* provide
+these boundaries to FixMyStreet. Once you've done this, you can associate the
+bodies you'll be sending reports to with these areas. This is easy to do in
+the FixMyStreet admin: you simply choose the area (or areas) from a drop-down
+list when you create or edit the body.
+
+## Where to get your boundary data from
+
+If the bodies you are going to be sending reports to are local government
+departments, it's possible that this data already exists. We use the admin
+boundary data from
+<a href="{{ "/glossary/#osm" | relative_url }}" class="glossary__link">OpenStreetMap</a>,
+and many countries' data is already available. If that's the case for you, then
+this is going to be easy! You just have to identify the areas you need, and
+tell FixMyStreet to ignore all the others.
+
+But if the boundaries you need are not already in Open Street Map -- maybe
+nobody has ever put them in, or maybe your government doesn't publish such data
+for people to use, or perhaps the areas your bodies use are not admin
+boundaries anyway -- you'll have to create your own.
+
+## The geometry of boundaries
+
+Areas often don't overlap -- because it's common for local government to
+arrange its jurisdiction so that each has its own area to cover.
+
+But actually the MapIt service is very flexible, and you can have areas that
+overlap, or be entirely separate and never touch, or even contain all or part
+of one another. This is because all FixMyStreet really cares about is asking
+MapIt "which areas is this pin in?" MapIt may reply with none, one, or many
+areas, depending on how your boundaries are arranged.
+
+Note that more than one body can cover the same area (actually it’s quite
+common). For example, two national bodies (the Highways Department and the
+Water Department) might both have the same national boundary data.
+
+Also, it's possible to associate a body in FixMyStreet with more than
+one area from MapIt. For example, a single port authority could be associated
+with the ports on three different islands.
+
+
+## Types of boundaries
+
+The type of boundary data you need depends on a number of factors, but will
+probably be one of these:
+
+ * ["Everywhere"](#everywhere) -- you can run FixMyStreet without a specific boundary
+ * [Simple approximate area](#approx-area) -- that is, just one area around the place you need
+ * [Simple approximate areas](#approx-areas) -- as above, but for multiple areas
+ * [Accurate OpenStreetMap data](#mysociety-mapit) -- the preferred option
+ * [Accurate data that isn't on OSM](#accurate) -- if you have your own boundary data, for example
+
+If you're not sure which is for you, read through the sections below.
+
+<!-- TODO add diagrams! Did some Isle of Wight ones but I don't like 'em -->
+
+<a name="everywhere"> </a>
+
+## "Everywhere"
+
+This is the simplest boundary: it's infinte, so anywhere the user clicks is
+inside the area called "everywhere".
+
+Use this type of boundary if:
+
+ * the bodies you're sending reports to don't depend on the whereabouts of the problem
+ * or all the problem reports are always sent to the same, single body
+ * you don't mind that FixMyStreet will never reject any problem report because it's too far away
+
+The advantage of using the boundary "Everywhere" is that it's very easy to set
+up. The disadvantage is that your FixMyStreet will accept clicks *anywhere* on
+the map. This may be acceptable if you are limiting your
+<a href="{{ "/glossary/#geocoder" | relative_url }}" class="glosssary">geocoder</a>
+to a very specific area.
+
+<dl class="reveal-on-click" data-reveal-noun="details">
+ <dt>
+ <h3>How to set this up</h3>
+ </dt>
+ <dd>
+ <p>
+ This is the default setup of a new FixMyStreet installation (if you used the
+ <a href="{{ "/install/install-script" | relative_url }}">installation script</a> or the
+ <a href="{{ "/install/ami" | relative_url }}">AMI install</a>).
+ </p>
+ <p>
+ Set
+ <code><a href="{{ "/customising/config/#mapit_url" | relative_url }}">MAPIT_URL</a></code>
+ to be blank, and set
+ <code><a href="{{ "/customising/config/#mapit_types" | relative_url }}">MAPIT_TYPES</a></code>
+ to the special value <code>ZZZ</code>. FixMyStreet will use a fake MapIt that always
+ returns "Everywhere" as the only area that contains the point &mdash; for any
+ location.
+ </p>
+ <p>
+ Your <code>conf/general.yml</code> file should contain this:
+ </p>
+<pre><code>MAPIT_URL: ''
+MAPIT_TYPES: ['ZZZ']
+MAPIT_ID_WHITELIST: [ ]
+</code></pre>
+ </dd>
+</dl>
+
+<a name="approx-area"> </a>
+
+## Simple approximate area
+
+Sometimes you just need a boundary to broadly determine if a pin in the map is
+too far away from the single area you're receiving reports for.
+
+Use this type of boundary if you:
+
+ * don't need an accurate boundary (for example, _"anything roughly near the town centre is OK"_)
+ * do want to prevent problem reports for locations that are not within this area
+
+<dl class="reveal-on-click" data-reveal-noun="details">
+ <dt>
+ <h3>How to set this up</h3>
+ </dt>
+ <dd>
+ <p>
+ You need to install your own MapIt instance, and add the area to that. The
+ MapIt admin interface (which uses the Django framework) lets you click-and-draw
+ a polygon over a map. Alternatively, we run a MapIt server for custom areas
+ like this, so &mdash; especially if you are just doing this as a probationary
+ trial &mdash; we may be able to host this for you (note though that we do
+ rate-limit calls to MapIt). Either send us
+ <a href="{{ "/glossary/#kml" | relative_url }}" class="glossary__link">KML shape files</a>,
+ or if you can't do that, maybe a clear image of the map with the boundary
+ drawn on it for us to copy.
+ </p>
+ <p>
+ In your <code>conf/general.yml</code>, you must set
+ <code><a href="{{ "/customising/config/#mapit_url" | relative_url }}">MAPIT_URL</a></code>
+ to either your MapIt or our custom one, and set
+ <code><a href="{{ "/customising/config/#mapit_types" | relative_url }}">MAPIT_TYPES</a></code>
+ to the areas you want (the actual values will depend on what that particular
+ MapIt is returning). You should also set
+ <code><a href="{{ "/customising/config/#mapit_id_whitelist" | relative_url }}">MAPIT_ID_WHITELIST</a></code>
+ to the ID of the single area you want.
+ </p>
+ <pre><code>MAPIT_URL: 'http://mapit.example.com'
+MAPIT_TYPES: ['CITY']
+MAPIT_ID_WHITELIST: [ 133 ]
+</code></pre>
+ </dd>
+</dl>
+
+<a name="approx-areas"> </a>
+
+## Simple approximate areas
+
+This is the same as the previous example, but shows that you can have multiple
+areas. This works best if they don't need to be very accurate &mdash; that is,
+no colinear borders.
+
+Use this type of boundary if you:
+
+ * don't need an accurate boundary (e.g. anything roughly in an area is OK)
+ * the boundaries don't adjoin, or are very simple (no crinkly edges)
+ * do want to prevent problem reports for locations that are not within these areas
+
+<dl class="reveal-on-click" data-reveal-noun="details">
+ <dt>
+ <h3>How to set this up</h3>
+ </dt>
+ <dd>
+ <p>
+ Same as previous example: either set up your own instance of MapIt, or ask to
+ have your boundaries added to our custom one. If you want us to host it, we'll
+ need <a href="{{ "/glossary/#kml" | relative_url }}" class="glossary__link">KML shape files</a>
+ or a graphic showing the boundary clearly shown so we can copy it.
+ </p>
+ <p>
+ Note that now there may be more than one type of area, and you'll need to explicitly
+ nominate every area you're interested in with
+ <code><a href="{{ "/customising/config/#mapit_id_whitelist" | relative_url }}">MAPIT_ID_WHITELIST</a></code>
+ (unless you want *all* the areas this MapIt returns for the given type, in
+ which case you can set it to be empty).
+ </p>
+ <pre><code>MAPIT_URL: 'http://mapit.example.com'
+MAPIT_TYPES: ['CITY', 'COUNTY']
+MAPIT_ID_WHITELIST: [ 133, 145, 12, 80 ]
+</code></pre>
+ </dd>
+</dl>
+
+<a name="mysociety-mapit"> </a>
+
+## Accurate OpenStreetMap data
+
+It's possible that the admin boundaries of local government in your area are
+already available in the OpenStreetMap project. If this is the case,
+FixMyStreet can automatically use them. **This is the easiest solution if the
+data you need is there** because we already run two servers
+([UK MapIt](https://mapit.mysociety.org) and
+[global MapIt](http://global.mapit.mysociety.org))
+that make this data available.
+
+Use this type of boundary if:
+
+ * the boundary data for the areas you need is already on OpenStreetMap
+
+<dl class="reveal-on-click" data-reveal-noun="details">
+ <dt>
+ <h3>How determine if the boundary data is available</h3>
+ </dt>
+ <dd>
+ <p>
+ Start by finding the <a href="{{ "/glossary/#latlong" | relative_url }}"
+ class="glossary__link">lat-long</a> of some of the places you want to cover,
+ and look them up on <a href="http://global.mapit.mysociety.org">global
+ MapIt</a> (or maybe the <a href="https://mapit.mysociety.org">UK one</a>).
+ If you see the "Areas covering this point" include the admin
+ boundaries you need, you're good to go! For example, here's
+ the <a
+ href="http://global.mapit.mysociety.org/point/4326/10.75,59.95.html">page
+ for Oslo, in Norway</a>.
+ </p>
+ <p>
+ Note that our MapIt servers' data may lag a little behind OSM, so
+ if it's not there, look on the
+ <a href="http://www.openstreetmap.org">OpenStreetMap website</a> just in
+ case it's been added since MapIt's last update. If so, let us
+ know, and we'll pull it in for you.
+ </p>
+ <p>
+ Here's an example of the steps to follow to find the data you need
+ to use global MapIt. This example uses Zurich as an example city.
+ </p>
+ <ol>
+ <li>
+ <p>
+ Go to <a href="http://nominamtim.openstreetmap.org">OpenStreetMap's
+ geocoder</a> and enter the name of the city, e.g., "Zurich,
+ Switzerland".
+ </p>
+ </li>
+ <li>
+ <p>
+ Check that's found the right place (and, if you want, check the map
+ is how you expected). Click on the <strong>details</strong> link just
+ below the name of the top hit. The details page lists lots of data,
+ including the centre point (lat/long values that will look something
+ like <code>-34.9059039,-56.1913569</code>).</p></li> <li><p>Go to <a
+ href="http://global.mapit.mysociety.org">global MapIt</a> and paste
+ those lat/long values into the text input.
+ </p>
+ </li>
+ <li>
+ <p>
+ MapIt will show you all the <a
+ href="http://global.mapit.mysociety.org/point/4326/8.55,47.366667.html">admin boundaries</a>
+ that contain that point. You're interested in
+ the ones that relate to bodies that serve those areas. For example,
+ if a district council fixes the potholes in that district.
+ Specifically, you need the <strong>Administrative Boundary
+ Levels</strong> (which will look like <code>O04</code> or
+ <code>O05</code>), which are the values for your
+ <code><a href="{{ "/customising/config/#mapit_types" | relative_url }}">MAPIT_TYPES</a></code>.
+ Remember this data is boundary data from OpenStreetMap &mdash;
+ if the boundaries you need are not shown, you may have to set up your
+ own (described below). You can also click on any of the boundaries
+ listed on MapIt to see the areas they actually cover on the map.
+ </p>
+ </li>
+ <li>
+ <p>
+ The individual <em>area_id</em>s are also useful, because you put
+ them into the <code><a href="{{ "/customising/config/#mapit_id_whitelist" | relative_url }}">MAPIT_ID_WHITELIST</a></code>.
+ </p>
+ </li>
+ </ol>
+ </dd>
+ <dt>
+ <h3>Using our MapIt servers: some restrictions</h3>
+ </dt>
+ <dd>
+ <p>
+ We run two public MapIt services: <a
+ href="https://mapit.mysociety.org">mapit.mysociety.org</a> covers the UK
+ (because that's where we're based, and it serves our own
+ <a href="www.fixmystreet.com">UK FixMySteet</a> site), and
+ <a href="http://global.mapit.mysociety.org">global.mapit.mysociety.org</a>,
+ which covers the whole world. The data we use for global MapIt is from
+ <a href="http://www.openstreetmap.org">OpenStreetMap</a>, so if someone has
+ put administrative boundary data for your country into OSM, before too
+ long global MapIt will have it too.
+ </p>
+ <p>
+ Please get in touch with us if you are expecting to generate a lot of
+ requests or <strong>if you are using it commercially</strong>. We
+ rate-limit calls to MapIt, so if your site gets really busy, you should
+ set up your own instance (we can help you, and the <a
+ href="https://github.com/mysociety/mapit">code is on GitHub</a>). But when
+ you're setting your site up to begin with, you can usually get it running
+ using one of our MapIt servers.
+ </p>
+ </dd>
+ <dt>
+ <h3>How to set this up</h3>
+ </dt>
+ <dd>
+ <p>
+ In your <code>conf/general.yml</code> file, point
+ <code><a href="{{ "/customising/config/#mapit_url" | relative_url }}">MAPIT_URL</a></code>
+ at the global MapIt server.
+ </p>
+ <p>
+ Find the areas you need by looking on the
+ <a href="http://global.mapit.mysociety.org">global MapIt website</a> or the
+ <a href="https://mapit.mysociety.org">UK one</a>. You must also nominate
+ the types of area these are (effectively the <em>level</em> of admin
+ boundary it is), and the generation. On global, the area types look
+ something like <code>[ 'O05', 'O06' ]</code>. (Note those contain capital
+ letter O followed by digits). To determine what types you need, look for
+ the codes marked &#8220;Administrative Boundary Levels&#8221; that MapIt
+ returns &mdash; for example, here's
+ <a href="http://global.mapit.mysociety.org/point/4326/8.55,47.366667.html">global
+ MapIt's data for Zurich</a>.
+ </p>
+ <p>
+ The UK MapIt types are different. For example, for UK FixMyStreet, we use:
+ </p>
+<pre><code>MAPIT_TYPES: [ 'DIS', 'LBO', 'MTD', 'UTA', 'CTY', 'COI', 'LGD' ]
+</code></pre>
+ <p>
+ which covers all the UK council types (for example, <code>DIS</code> is district council,
+ <code>CTY</code> is county council).
+ </p>
+ <p>
+ Finally, limit your installation to the specific areas you're interested
+ in (otherwise you'll be getting areas from the whole world). Identify the
+ specific areas you want to use, and list them explicitly in
+ <code><a href="{{ "/customising/config/#mapit_id_whitelist" | relative_url }}">MAPIT_ID_WHITELIST</a></code>.
+ You should also set
+ <code><a href="{{ "/customising/config/#mapit_generation" | relative_url }}">MAPIT_GENERATION</a></code>,
+ so that your areas can still be found when we update the global MapIt data.
+ </p>
+<pre><code>MAPIT_URL: 'http://global.mapit.mysociety.org'
+MAPIT_TYPES: ['O06','O07']
+MAPIT_ID_WHITELIST: ['12345','345432','978638']
+MAPIT_GENERATION: 3
+</code></pre>
+
+ </dd>
+
+</dl>
+
+<a name="accurate"> </a>
+
+## Accurate data that isn't on OSM
+
+Use this type of boundary if:
+
+ * you need accurate boundaries because the different bodies that
+ solve problems in your region serve specific areas that are geometrically
+ complex and/or are precisely adjacent
+ * the boundary data for the areas you need are not already on OpenStreetMap
+ * but you do have access to this data from some other source
+
+This means you have to source the data yourself -- either by getting your local
+government to release it, or else drawing it yourself. Then you need to import
+this data into a MapIt server and use that.
+
+<dl class="reveal-on-click" data-reveal-noun="details">
+ <dt>
+ <h3>How to set this up</h3>
+ </dt>
+ <dd>
+ <p>
+ Ideally, if you can source the data from your local government (which
+ means it's definitive), then it's great if you can add it (as
+ admin boundary data) to the OpenStreetMap project. Our global MapIt will
+ subsequently import it and your FixMyStreet can then use it as described
+ in the previous example. If you're going to do that, <strong>the
+ data must be open data</strong> and you should probably ask about it on
+ the <a href="http://lists.openstreetmap.org/listinfo/imports">OSM import
+ list</a> first. Of course, if you do this then anyone else in the world
+ who wants the data will be able to use it too, which is why we encourage
+ this approach.
+ </p>
+ <p>
+ But if you can't do that, or the boundary data you have is not
+ definitive, you can create your own. Use any good GIS software to plot
+ the boundaries accurately, and then export it as
+ <a href="{{ "/glossary/#kml" | relative_url }}" class="glossary__link">KML shape files</a>.
+ MapIt can import these, so you can then either run your own MapIt
+ instance, or ask us to add it to our custom one.
+ </p>
+ </dd>
+</dl>
+
+## Can you see the boundaries?
+
+FixMyStreet doesn't normally display the admin areas and boundaries on the maps
+(mainly because most users really don't care &mdash; they just want to report
+a problem). But it *is* possible, with some customisation, to change this
+behaviour.
+
+If you just want to see a boundary drawn on a map to check that it's covering
+the area you want, you can see this by going to the MapIt server it's on, and
+looking at that area's HTML page. For example, see the [boundary for
+Norway](http://global.mapit.mysociety.org/area/363186.html) on the global MapIt
+server.
+
+
+
diff --git a/docs/customising/checklist.md b/docs/customising/checklist.md
new file mode 100644
index 000000000..b066a4279
--- /dev/null
+++ b/docs/customising/checklist.md
@@ -0,0 +1,206 @@
+---
+layout: page
+title: Customising checklist
+---
+
+# Customising checklist
+
+<p class="lead">
+ Every time we help set up a new, custom FixMyStreet site, we follow the same
+ basic process to make sure all the key things get done. We've listed the
+ steps here so you can follow them too.
+</p>
+
+## Checklist: 13 things to do
+
+To create a custom FixMyStreet installation, these are the key things you need
+to do. You don't have to do them *exactly* in this order -- some can be done
+at the same time as others -- but if you're not sure then just work through the list.
+
+
+<dl class="reveal-on-click" data-reveal-noun="steps">
+ <dt>
+ <h3>Pick a name</h3>
+ </dt>
+ <dd>
+ You need a name for your
+ <a href="{{ "/glossary/#cobrand" | relative_url }}" class="glossary__link">cobrand</a>
+ right at the start because that's the name you'll use for the directories
+ where your own resources and templates go.
+ <p>
+ Your name needs to be unique (that is, no other FixMyStreet cobrands are
+ already using it), suitable as a directory name (so no punctuation), and
+ ideally related to the domain name you're going to use for it (although
+ this isn't 100% obligatory).
+ </p>
+ <p>
+ For example, if your project is called FixMyPark, the cobrand name will
+ be <code>fixmypark</code>.
+ </p>
+ </dd>
+ <dt>
+ <h3>Set up the domain name
+</h3>
+ </dt>
+ <dd>
+ If you already own the domain name,
+ you're good to go. But if this is a new project and you don't have the
+ domain set up already, don't leave it too late to register the domain
+ and point it at your server.
+ </dd>
+ <dt>
+ <h3>Translate into language(s) you need</h3>
+ </dt>
+ <dd>
+ If FixMyStreet doesn't already have translations for the language(s) you
+ need, you can start work on that right away &mdash; see
+ <a href="{{ "/customising/language/" | relative_url }}">more about languages</a>.
+ </dd>
+ <dt>
+ <h3>Install the software on the server</h3>
+ </dt>
+ <dd>
+ There are several different ways of doing this &mdash; see
+ <a href="{{ "/install/" | relative_url }}">installation instructions</a>.
+ <p>
+ Even if you're not hosting the site yourself, you might want to install
+ the software in order to see how your customisation looks before putting
+ it live.
+ </p>
+ </dd>
+ <dt>
+ <h3>Secure access to the admin</h3>
+ </dt>
+ <dd>
+ Make sure you're being challenged to provide a username and password when
+ accessing the admin at <code>/admin</code>.
+ <p>
+ Typically this means using creating a superuser. If you've
+ not already done so, run the `bin/createsuperuser` script to create a user
+ that has access to the admin.
+ </p>
+ </dd>
+ <dt>
+ <h3>Change the colour scheme</h3>
+ </dt>
+ <dd>
+ See <a href="{{ "/customising/css/" | relative_url }}">changing colour and CSS</a>
+ for detailed instructions.
+ <p>
+ You can just change the colour variables without needing to touch any other
+ CSS.
+ </p>
+ </dd>
+ <dt>
+ <h3>Change the logo</h3>
+ </dt>
+ <dd>
+ You'll need an understanding of CSS in order to change the logo &mdash;
+ it's optimised in the FixMyStreet design for good perfomance on old or
+ narrow clients, which makes it a little bit more difficult than just
+ dropping in a graphics file.
+ <p>
+ We'll be adding instructions later, but meanwhile see the page
+ <a href="{{ "/customising/css/" | relative_url }}">about changing the CSS</a>.
+ </p>
+ </dd>
+ <dt>
+ <h3>Write your own FAQ</h3>
+ </dt>
+ <dd>
+ You almost certainly need to re-write the FAQ and other information pages
+ to match your project.
+ <p>
+ To do this, copy the template files into your own cobrand's directory and
+ rewrite them. The generic base FAQ can be found at
+ <code>templates/web/base/about/faq-en-gb.html</code>
+ </p>
+ <p>
+ See <a href="{{ "/customising/templates/" | relative_url }}">more about templates</a>.
+ </p>
+ </dd>
+ <dt>
+ <h3>Limit geocoder lookups to your area <!-- NEW --></h3>
+ </dt>
+ <dd>
+ When someone enters a place name, you only want your FixMyStreet to look
+ for it in the place your site covers. This is controlled by the
+ <code><a href="{{ "/customising/config/#geocoding_disambiguation" | relative_url }}">GEOCODING_DISAMBIGUATION</a></code>
+ setting.
+ See <a href="{{ "/customising/geocoder/" | relative_url }}">more about the geocoder</a>.
+ <p>
+ We've listed this separately from the other config settings because it
+ may take a little bit of testing to see what options work best &mdash;
+ this depends on which geocoder you are using.
+ </p>
+ </dd>
+ <dt>
+ <h3>Configure your admin boundaries (MapIt)</h3>
+ </dt>
+ <dd>
+ You need to decide what kind of boundary data you'll be using &mdash; see
+ <a href="{{ "/customising/boundaries/" | relative_url }}">more about boundaries</a>.
+ <p>
+ As part of that work, you'll need to set
+ <code><a href="{{ "/customising/config/#mapit_url" | relative_url }}">MAPIT_URL</a></code>
+ and the other MapIt config settings to match the service you're using.
+ </p>
+ </dd>
+ <dt>
+ <h3>Set non-default config settings</h3>
+ </dt>
+ <dd>
+ Many of the
+ <a href="{{ "/customising/config/" | relative_url }}">configuration settings</a>
+ can be left with their defaults, but some you <em>must</em> change.
+ <p>
+ As well as system settings (for example,
+ <code><a href="{{ "/customising/config/#fms_db_name" | relative_url }}">FMS_DB_NAME</a></code>),
+ every new site needs custom
+ <code><a href="{{ "/customising/config/#email_domain" | relative_url }}">EMAIL_DOMAIN</a></code>
+ and
+ <code><a href="{{ "/customising/config/#example_places" | relative_url }}">EXAMPLE_PLACES</a></code>
+ settings. Make sure the example places you choose really do work if you enter them
+ as the location on the front page.
+ </p>
+ <p>
+ Even though your site might work with other settings left as defaults, you should go
+ through the <em>whole</em> <code>cong/general.yml</code> file to check everything is how
+ you want it.
+ </p>
+ </dd>
+ <dt>
+ <h3>Create the bodies (authorities, councils)</h3>
+ </dt>
+ <dd>
+ Once your site is running log into the admin and
+ <a href="{{ "/running/bodies_and_contacts/" | relative_url }}">add the bodies</a>.
+ <p>
+ You should have set up the
+ <a href="{{ "/customising/boundaries/" | relative_url }}">admin boundaries</a>
+ by this stage, because you need to associate each body with the area it covers.
+ For more information, see
+ <a href="{{ "/customising/fms_and_mapit/" | relative_url }}">how FixMyStreet uses MapIt</a>.
+ </p>
+ </dd>
+ <dt>
+ <h3>Add category names &amp; contact emails</h3>
+ </dt>
+ <dd>
+ Once you've created the bodies to whom reports will be sent, you can add
+ their problem categories (for example, "Potholes", "Streetlights"). At the
+ same time, add the contact email addresses for each one &mdash; see <a
+ href="{{ "/running/bodies_and_contacts/" | relative_url }}">more about
+ contacts and categories</a>.
+ </dd>
+</dl>
+
+
+## Further customisation
+
+Remember that this just covers the key parts of a custom installation. There's
+a lot more you can change &mdash; for example, you can write custom Perl code
+for the <a href="{{ "/customising/cobrand-module/" | relative_url }}">Cobrand
+module</a> if you want to override specific behaviour not covered by config
+variables.
+
diff --git a/docs/customising/cobrand-module.md b/docs/customising/cobrand-module.md
new file mode 100644
index 000000000..fb771ab26
--- /dev/null
+++ b/docs/customising/cobrand-module.md
@@ -0,0 +1,105 @@
+---
+layout: page
+title: Customising with a Cobrand module
+---
+
+# Cobrand module
+
+If you need customistation beyond what templates, configuration variables, and
+translations can offer, then you will have to have a Cobrand module. These are
+automatically loaded according to the current Cobrand and can be found in
+`perllib/FixMyStreet/Cobrand/`. There is a default Cobrand (`Default.pm`)
+which all Cobrands should inherit from. A Cobrand module can then override any
+of the methods from the default Cobrand.
+
+Many of the functions in the Cobrand module are used by FixMyStreet in the UK
+to allow the site to offer versions localised to a single authority and should
+not be needed for most installs. Listed below are some of the options that
+can be changed:
+
+* language_override
+
+ Return a language code string from this function if you wish your cobrand
+to always be in a particular language, rather than try and work it out from the
+domain name or the browser’s settings.
+
+* add_response_headers
+
+ Any extra headers you wish to send with your HTTP responses. For example,
+ fixmystreet.com uses this to send a Content-Security-Policy header.
+
+* on_map_default_max_pin_age
+
+ How far back to go by default showing pins on your around map.
+
+* areas_on_around
+
+ If you would like to plot the boundaries of MapIt IDs on an around page
+(not just reports page), you specify them here.
+
+* pin_colour
+
+ This can be used if you wish to specify different pin colours depending upon
+some aspect of the report - its state, category, and so on.
+
+* pin_new_report_colour
+
+ What colour to use for the pin when reporting a new issue.
+
+* geocode_postcode
+
+ This function is used to convert postcodes (zip codes, etc.) entered into a
+latitude and longitude, if there's a different way from your geocoder of doing so
+(e.g. a MapIt install). If the text passed is not a valid postcode then an
+error should be returned. If you do not want to use postcodes, just do not define
+this function.
+
+ If the postcode is valid and can be converted then the return value should
+look like this:
+
+ return { latitude => $latitude, longitude => $longitude };
+
+ If there is an error it should look like this:
+
+ return { error => $error_message };
+
+* find_closest and find_closest_address_for_rss
+
+ These are used to provide information on the closest street to the point of
+the address in reports and RSS feeds or alerts.
+
+* allow_photo_upload
+
+ Return 0 to disable the photo upload field.
+
+* allow_photo_display
+
+ Return 0 to disable the display of uploaded photos.
+
+* remove_redundant_areas
+
+ This is used to filter out any overlapping jurisdictions from MapIt results
+where only one of the authorities actually has responsibility for the events
+reported by the site. An example would be a report in a city where MapIt
+has an ID for the city council and the state council (and they are both the
+same MapIt area type) but problems are only reported to the state. In this case
+you could remove the ID for the city council from the results.
+
+ With the new bodies handling, a better way to handle this would be to simply
+have a body that only covered the state council administrative area.
+
+* short_name
+
+ This is used to turn the full authority name returned by MapIt into a short
+name.
+
+* send_questionnaires
+
+ By default, FixMyStreet [sends questionnaires]({{ "/running/surveys" | relative_url }})
+ (sometimes called _surveys_) four weeks after a user submitted a report. The
+ questionnaire encourages them to update the
+ <a href="{{ "/glossary/#state" | relative_url }}" class="glossary__link">state</a>
+ of the report. Return 0 to disable this feature so that surveys are never
+ sent.
+
+
diff --git a/docs/customising/config.md b/docs/customising/config.md
new file mode 100644
index 000000000..9f48bad7e
--- /dev/null
+++ b/docs/customising/config.md
@@ -0,0 +1,1122 @@
+---
+layout: page
+title: Configuration settings
+---
+
+# Configuration settings
+
+<p class="lead">
+ You can control much of how FixMyStreet looks and behaves just by
+ changing the config settings.
+</p>
+
+## The general configuration file
+
+<div class="attention-box info">
+You can look at a summary of the live configuration of your site by going to
+the Configuration page of your administration interface, at
+<code>/admin/config</code>.
+</div>
+
+The FixMyStreet code ships with an example configuration file:
+`conf/general.yml-example`.
+
+As part of the [installation process]({{ "/install " | relative_url }}), the example
+file gets copied to `conf/general.yml`. You **must** edit this file to suit
+your needs.
+
+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.
+
+## Config settings by topic
+
+The following are all the configuration settings that you can change in `conf/general.yml`.
+
+### Database config
+
+* <code><a href="#fms_db_host">FMS_DB_HOST</a></code>,
+<code><a href="#fms_db_port">FMS_DB_PORT</a></code>,
+<code><a href="#fms_db_name">FMS_DB_NAME</a></code>,
+<code><a href="#fms_db_user">FMS_DB_USER</a></code>, and
+<code><a href="#fms_db_pass">FMS_DB_PASS</a></code>
+
+### Site settings and behaviour
+
+* <code><a href="#allowed_cobrands">ALLOWED_COBRANDS</a></code>
+* <code><a href="#rss_limit">RSS_LIMIT</a></code>
+* <code><a href="#open311_limit">OPEN311_LIMIT</a></code>
+* <code><a href="#all_reports_per_page">ALL_REPORTS_PER_PAGE</a></code>
+* <code><a href="#area_links_from_problems">AREA_LINKS_FROM_PROBLEMS</a></code>
+
+### URLs and directories
+
+* <code><a href="#base_url">BASE_URL</a></code>
+* <code><a href="#secure_proxy_ssl_header">SECURE_PROXY_SSL_HEADER</a></code>
+* <code><a href="#upload_dir">UPLOAD_DIR</a></code>
+* <code><a href="#geo_cache">GEO_CACHE</a></code>
+* <code><a href="#admin_base_url">ADMIN_BASE_URL</a></code>
+
+### Emailing
+
+* <code><a href="#email_domain">EMAIL_DOMAIN</a></code>
+* <code><a href="#contact_email">CONTACT_EMAIL</a></code>
+* <code><a href="#contact_name">CONTACT_NAME</a></code>
+* <code><a href="#do_not_reply_email">DO_NOT_REPLY_EMAIL</a></code>
+* SMTP server settings: <code><a href="#smtp_smarthost">SMTP_SMARTHOST</a></code>,
+ <code><a href="#smtp_type">SMTP_TYPE</a></code>,
+ <code><a href="#smtp_port">SMTP_PORT</a></code>,
+ <code><a href="#smtp_username">SMTP_USERNAME</a></code>,
+ and <code><a href="#smtp_password">SMTP_PASSWORD</a></code>
+
+### Login methods, authentication
+
+* Social login: <code><a href="#facebook_app_id">FACEBOOK_APP_ID</a></code>,
+ <code><a href="#facebook_app_secret">FACEBOOK_APP_SECRET</a></code>,
+ <code><a href="#twitter_key">TWITTER_KEY</a></code>, and
+ <code><a href="#twitter_secret">TWITTER_SECRET</a></code>
+* SMS text authentication: <code><a href="#sms_authentication">SMS_AUTHENTICATION</a></code>,
+ <code><a href="#phone_country">PHONE_COUNTRY</a></code>,
+ <code><a href="#twilio_account_sid">TWILIO_ACCOUNT_SID</a></code>,
+ <code><a href="#twilio_auth_token">TWILIO_AUTH_TOKEN</a></code>, and
+ <code><a href="#twilio_from_parameter">TWILIO_FROM_PARAMETER</a></code>
+* <code><a href="#login_required">LOGIN_REQUIRED</a></code>
+* <code><a href="#signups_disabled">SIGNUPS_DISABLED</a></code>
+
+### Staging site (not production) behaviour
+
+* <code><a href="#staging_site">STAGING_SITE</a></code>
+* <code><a href="#staging_flags">STAGING_FLAGS</a></code>
+
+### MapIt (admin boundary service)
+
+* <code><a href="#mapit_url">MAPIT_URL</a></code>
+* <code><a href="#mapit_types">MAPIT_TYPES</a></code>
+* <code><a href="#mapit_api_key">MAPIT_API_KEY</a></code>
+* <code><a href="#mapit_id_whitelist">MAPIT_ID_WHITELIST</a></code>
+* <code><a href="#mapit_generation">MAPIT_GENERATION</a></code>
+* <code><a href="#mapit_types_children">MAPIT_TYPES_CHILDREN</a></code>
+
+### Localisation and maps
+
+* <code><a href="#languages">LANGUAGES</a></code>
+* <code><a href="#time_zone">TIME_ZONE</a></code>
+* <code><a href="#geocoder">GEOCODER</a></code>
+* <code><a href="#geocoding_disambiguation">GEOCODING_DISAMBIGUATION</a></code>
+* <code><a href="#example_places">EXAMPLE_PLACES</a></code>
+* <code><a href="#map_type">MAP_TYPE</a></code>
+* <code><a href="#google_maps_api_key">GOOGLE_MAPS_API_KEY</a></code>
+* <code><a href="#bing_maps_api_key">BING_MAPS_API_KEY</a></code>
+
+### Sundry external services
+
+* <code><a href="#gaze_url">GAZE_URL</a></code>
+* <code><a href="#message_manager_url">MESSAGE_MANAGER_URL</a></code>
+
+---
+
+## All the general settings
+
+<dl class="glossary">
+
+ <dt>
+ <a name="fms_db_host"><code>FMS_DB_HOST</code></a>,
+ <a name="fms_db_port"><code>FMS_DB_PORT</code></a>,
+ <a name="fms_db_name"><code>FMS_DB_NAME</code></a>,
+ <a name="fms_db_user"><code>FMS_DB_USER</code></a> &amp;
+ <a name="fms_db_pass"><code>FMS_DB_PASS</code></a>
+ </dt>
+ <dd>
+ These are the PostgreSQL database details for FixMyStreet.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>
+ FMS_DB_HOST: 'localhost'<br>
+ FMS_DB_PORT: '5432'<br>
+ FMS_DB_NAME: 'fms'<br>
+ FMS_DB_USER: 'fmsuser'<br>
+ FMS_DB_PASS: 'aSecretWord'
+ </code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="base_url"><code>BASE_URL</code></a>
+ </dt>
+ <dd>
+ The base URL of your site.
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <code>BASE_URL: 'http://www.example.org'</code>
+ </li>
+ <li>
+ <p>
+ Use this if you're using the Catalyst development server:
+ </p>
+ <code>BASE_URL: 'http://localhost:3000'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="secure_proxy_ssl_header"><code>SECURE_PROXY_SSL_HEADER</code></a>
+ </dt>
+ <dd>
+ If you are behind a proxy that is performing SSL termination, and so
+ FixMyStreet is e.g. responding locally on a non-HTTPS connection, then you
+ need to make your proxy set a custom HTTP header saying that the request
+ was via HTTPS, and then set this value to a two-element list containing the
+ trusted HTTP header and the required value.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>SECURE_PROXY_SSL_HEADER: [ 'X-Forwarded-Proto', 'https' ]</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="email_domain"><code>EMAIL_DOMAIN</code></a>,
+ <a name="contact_email"><code>CONTACT_EMAIL</code></a> &amp;
+ <a name="contact_name"><code>CONTACT_NAME</code></a>
+ </dt>
+ <dd>
+ The email domain used for emails, and the contact name and email
+ for admin use.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>
+ EMAIL_DOMAIN: 'example.org'<br>
+ CONTACT_EMAIL: 'team@example.org'<br>
+ CONTACT_NAME: 'FixMyStreet team'
+ </code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="do_not_reply_email"><code>DO_NOT_REPLY_EMAIL</code></a>
+ </dt>
+ <dd>
+ The address used for emails you don't expect a reply to (for example,
+ confirmation emails). This can be the same as
+ <code><a href="#contact_email">CONTACT_EMAIL</a></code>, of course, if you don't have a special address.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>DO_NOT_REPLY_EMAIL: 'do-not-reply@example.org'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="staging_site"><code>STAGING_SITE</code></a>
+ </dt>
+ <dd>
+ Is this site a
+ <a href="{{ "/glossary/#staging" | relative_url }}" class="glossary__link">staging</a>
+ (or <a href="{{ "/glossary/#development" | relative_url }}" class="glossary__link">development</a>)
+ site?
+ <p>
+ On a staging site, templates/CSS modified times aren't cached. Staging
+ sites also don't send reports to bodies unless explicitly configured to
+ (see <code><a href="#staging_flags">STAGING_FLAGS</a></code>)
+ &mdash; this means you can easily test your site without really sending
+ emails to the bodies' contacts that may be in your database.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ If this is your live
+ <a href="{{ "/glossary/#production" | relative_url }}" class="glossary__link">production</a>
+ server:
+ <p>
+ <code>STAGING_SITE: 0</code>
+ </p>
+ </li>
+ <li>
+ If this is a development or staging server:
+ <p>
+ <code>STAGING_SITE: 1</code>
+ </p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="staging_flags"><code>STAGING_FLAGS</code></a>
+ </dt>
+ <dd>
+ <p>
+ A variety of flags that change the behaviour of a site when
+ <code><a href="#staging_site">STAGING_SITE</a></code> is <code>1</code>.
+ <code>send_reports</code> being set to 0 will
+ <a href="{{ "/customising/send_reports" | relative_url }}">send
+ reports</a> to the reporter <em>instead of</em> the relevant body's
+ contact address; <code>skip_checks</code> will stop cobrands from
+ performing some checks such as the map pin location being within their
+ covered area, which makes testing multiple cobrands much easier;
+ <code>enable_appcache</code> lets you say whether the appcache should be
+ active or not.
+ </p>
+ <p>
+ Note that this setting is only relevant on a
+ <a href="{{ "/glossary/#staging" | relative_url }}" class="glossary__link">staging</a>
+ server.
+ On your
+ <a href="{{ "/glossary/#production" | relative_url }}" class="glossary__link">production</a>
+ server (where
+ <code><a href="#staging_site">STAGING_SITE</a></code> is <code>0</code>)
+ it will be ignored.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+<pre>
+STAGING_FLAGS:
+ send_reports: 0
+ skip_checks: 1
+ enable_appcache: 0
+</pre>
+ </div>
+ <p>
+ Any reports created will now be sent to the email of the reporter
+ and <em>not</em> the body's; any location checks are skipped, and
+ we won't ever use appcache. Great for testing!
+ </p>
+ </dd>
+
+ <dt>
+ <a name="example_places"><code>EXAMPLE_PLACES</code></a>
+ </dt>
+ <dd>
+ The suggested input for a place name or names. By default, this appears
+ as a placeholder in the text input on FixMyStreet's front page, and in
+ alert emails. It defaults to displaying "High Street, Main Street".
+ <p>
+ You should ensure that the example places do return clear,
+ relevant results if they're entered in the font page text input
+ &mdash; this will probably depend on how you've set
+ <code><a href="#geocoding_disambiguation">GEOCODING_DISAMBIGUATION</a></code>.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ The default behaviour is this, which you should certainly change:
+ <p>
+ <code>EXAMPLE_PLACES: [ 'High Street', 'Main Street' ]</code>
+ </p>
+ </li>
+ <li>
+ <code>EXAMPLE_PLACES: [ 'Iffley Road', 'Park St, Woodstock' ]</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="languages"><code>LANGUAGES</code></a>
+ </dt>
+ <dd>
+ An array of languages the site supports, each in the following format:
+ <p>
+ <em>&lt;language code&gt;,&lt;pretty name&gt;,&lt;locale&gt;</em>
+ </p>
+ <p>
+ Some important things to note:
+ </p>
+ <ul>
+ <li>
+ Put the default language as the first entry in the list.
+ </li>
+ <li>
+ Don't put any extra spaces in the strings (e.g., after the commas).
+ </li>
+ <li>
+ Remember that if you want your site to run in languages other than
+ English, you'll also need to check that the translations are
+ available, and your system supports the appropriate
+ <a href="{{ "/glossary/#locale" | relative_url }}" class="glossary__link">locales</a>.
+ </li>
+ </ul>
+ <p>
+ Just adding a language here does not necessarily mean FixMyStreet will
+ always use it (for example, a language coded subdomain name or browser preference may be considered). See this page about
+ <a href="{{ "/customising/language" | relative_url }}">languages and FixMyStreet</a> for more information.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+<pre>
+LANGUAGES:
+ - 'en-gb,English,en_GB'
+</pre>
+ </li>
+ <li>
+<pre>
+LANGUAGES:
+ - 'de,German,de_DE'
+ - 'en-gb,English,en_GB'
+</pre>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="time_zone"><code>TIME_ZONE</code></a>
+ </dt>
+ <dd>
+ If you're running an installation that is being used in a different time zone
+ from the server, set the time zone here. Use a
+ <a href="http://en.wikipedia.org/wiki/List_of_tz_database_time_zones">standard time zone (TZ) string</a>.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>TIME_ZONE: 'Asia/Manila'</code>
+ </li>
+ <li>
+ Leave the setting blank to use your server's default:
+ <p><code>TIME_ZONE: ''</code></p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="upload_dir"><code>UPLOAD_DIR</code></a> &amp;
+ <a name="geo_cache"><code>GEO_CACHE</code></a>
+ </dt>
+ <dd>
+ The file locations for uploaded photos and cached geocoding results.
+ Normally you don't need to change these settings from the examples.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>
+ UPLOAD_DIR: '../upload/'<br>
+ GEO_CACHE: '../cache/'
+ </code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <code><a name="facebook_app_id">FACEBOOK_APP_ID</a></code> &amp;
+ <code><a name="facebook_app_secret">FACEBOOK_APP_SECRET</a></code>
+ </dt>
+ <dd>
+ If these parameters are set to a Facebook App's ID and secret, then
+ a user will be able to log in using their Facebook account when reporting,
+ updating, or logging in. <a href="../login/">More details</a>
+ </dd>
+
+ <dt>
+ <code><a name="twitter_key">TWITTER_KEY</a></code> &amp;
+ <code><a name="twitter_secret">TWITTER_SECRET</a></code>
+ </dt>
+ <dd>
+ If these parameters are set to a Twitter App's key and secret, then
+ a user will be able to log in using their Twitter account when reporting,
+ updating, or logging in. <a href="../login/">More details</a>
+ </dd>
+
+ <dt>
+ <code><a name="sms_authentication">SMS_AUTHENTICATION</a></code>
+ </dt>
+ <dd>
+ Set this to 1 if you wish people to be able to use their mobiles as login
+ identifiers, receiving confirmation codes by text to report, update or
+ login in a similar way to how they receive a link in a confirmation email.
+ <a href="../login/">More details</a>
+ </dd>
+
+ <dt>
+ <code><a name="phone_country">PHONE_COUNTRY</a></code>
+ </dt>
+ <dd>
+ Set this to the country code of where you are operating the site, so that
+ phone number parsing knows how to deal with national phone numbers entered.
+ </dd>
+
+ <dt>
+ <a name="twilio_account_sid"><code>TWILIO_ACCOUNT_SID</code></a> &amp;
+ <a name="twilio_auth_token"><code>TWILIO_AUTH_TOKEN</code></a>
+ </dt>
+ <dd>
+ These are your Twilio account details to use for sending text messages for
+ report and update verification.
+ See the <a href="https://www.twilio.com/docs/usage/api">Twilio docs</a> for more information.
+ </dd>
+
+ <dt>
+ <a name="twilio_from_parameter"><code>TWILIO_FROM_PARAMETER</code></a>
+ </dt>
+ <dd>
+ This is the phone number or alphanumeric string to use as the From of any
+ sent text messages.
+ You must specify either this or <code>TWILIO_MESSAGING_SERVICE_SID</code>.
+ See the <a href="https://www.twilio.com/docs/sms/send-messages">Twilio docs</a> for more information.
+ </dd>
+
+ <dt>
+ <a name="twilio_from_parameter"><code>TWILIO_MESSAGING_SERVICE_SID</code></a>
+ </dt>
+ <dd>
+ This is the unique id of the Twilio Messaging Service you want to associate with this message.
+ You must specify either this or <code>TWILIO_FROM_PARAMETER</code>.
+ See the <a href="https://www.twilio.com/docs/sms/send-messages">Twilio docs</a> for more information.
+ </dd>
+
+ <dt>
+ <a name="login_required"><code>LOGIN_REQUIRED</code></a>
+ </dt>
+ <dd>
+ If you're running an installation that should only be accessible to logged
+ in people, set this variable.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>LOGIN_REQUIRED: 1</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="signups_disabled"><code>SIGNUPS_DISABLED</code></a>
+ </dt>
+ <dd>
+ If you don't want any new people to be able to use the site, only the users
+ you have already created, then set this variable.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>SIGNUPS_DISABLED: 1</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="mapit_url"><code>MAPIT_URL</code></a>,
+ <a name="mapit_types"><code>MAPIT_TYPES</code></a>,
+ <a name="mapit_api_key"><code>MAPIT_API_KEY</code></a>
+ </dt>
+ <dd>
+ FixMyStreet uses the external service MapIt to map locations (points) to
+ administrative areas: see this
+ <a href="{{ "/customising/fms_and_mapit" | relative_url }}">explanation of MapIt</a>.
+ <!-- TODO link to explanation of boundaries -->
+ <p>
+ You must provide the URL of a MapIt server, and nominate what types of
+ area from it you want to use. If you leave this blank, a default area
+ will be used everywhere (a URL needs to be given for non-web things, like sending of reports, to function). <!-- TODO explain this: function? -->
+ If the MapIt you are using requires an API key, you can provide one.
+ </p>
+ <p>
+ See also <code><a href="#mapit_id_whitelist">MAPIT_ID_WHITELIST</a></code> to
+ efficiently limit the areas you need (especially if you're using
+ global MapIt).
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ If using the Catalyst development server, set to:
+ <p><code>
+ MAPIT_URL: 'http://localhost:3000/fakemapit/'<br>
+ MAPIT_TYPES: [ 'ZZZ' ]
+ </code></p>
+ </li>
+ <li>
+ In the UK, you probably want, to cover all councils:
+ <p><code>
+ MAPIT_URL: 'https://mapit.mysociety.org/'<br>
+ MAPIT_API_KEY: '12345'<br>
+ MAPIT_TYPES: [ 'DIS', 'LBO', 'MTD', 'UTA', 'CTY', 'COI', 'LGD' ]
+ </code></p>
+ <p>
+ ...but perhaps <code>MAPIT_TYPES: [ 'WMC' ]</code>
+ if you want to report on a per-constituency basis?
+ </p>
+ </li>
+ <li>
+ If our global MapIt (which is loaded with OpenStreetMap data)
+ contains boundaries you can use:
+ <p><code>
+ MAPIT_URL: 'http://global.mapit.mysociety.org/'
+ </code></p>
+ <p>
+ And then specify whichever type code have the boundaries you want:
+ </p>
+ <p><code>MAPIT_TYPES: [ 'O06' ]</code></p>
+ <p>
+ OSM type codes consist of the letter O followed by two digits
+ indicating the type of boundary. Typically, the higher the number,
+ the more specfic (localised) the boundary type.
+ </p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="mapit_id_whitelist"><code>MAPIT_ID_WHITELIST</code></a>
+ </dt>
+ <dd>
+ If you are using global MapIt (see
+ <code><a href="#mapit_url">MAPIT_URL</a></code>),
+ you might want to restrict FixMyStreet usage
+ to only one or more areas, rather than <em>all</em> areas of the
+ specified type (afer all, there are a lot of <code>O04</code> boundaries
+ in the whole world, for example). Provide a list of all the MapIt
+ IDs that your FixMyStreet should recognise.
+ <p>
+ Note that you must still set <code><a href="#mapit_types">MAPIT_TYPES</a></code> to match
+ the type or types of each of these areas. And we recommend you set
+ <code><a href="#mapit_generation">MAPIT_GENERATION</a></code> too.
+ </p>
+ <p>
+ We recommend you use this setting, because doing so can improves the efficiency of your site's calls to MapIt considerably.
+ </p>
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ If you don't specify a whitelist, all results (of the given area
+ type) will be considered. This may be OK if you're using a MapIt
+ server which is already only returning relevant results.
+ <p><code>MAPIT_ID_WHITELIST: []</code></p>
+ </li>
+ <li>
+ Otherwise, explicitly list the IDs (from the MapIt server you're
+ using) of the areas you're interested in:
+ <p>
+ <code>MAPIT_ID_WHITELIST: [ 240838, 246176, 246733 ]</code>
+ </p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="mapit_generation"><code>MAPIT_GENERATION</code></a>
+ </dt>
+ <dd>
+ If you have set
+ <code><a href="#mapit_id_whitelist">MAPIT_ID_WHITELIST</a></code>, then you
+ should also specify the generation of MapIt data you are using, especially
+ if you are using our global MapIt service.
+ <p>
+ Global MapIt uses <a href="{{ "/glossary/#osm" | relative_url }}"
+ class="glossary__link">OpenStreetMap</a> data. From time to time we import the latest
+ data in order to pull in newly-added boundaries, or reflect changes to existing
+ ones. When this happens, the area IDs may change, which means the values in your
+ <code><a href="#mapit_id_whitelist">MAPIT_ID_WHITELIST</a></code> might no longer
+ be correct (because, by default, MapIt returns values from the <em>latest</em>
+ generation of data). Use the <code>MAPIT_GENERATION</code> setting to lock
+ the area IDs in your whitelist &mdash; and the geometry described by their boundary
+ data &mdash; to the specific generation they belong to. MapIt's generations
+ are numbered with an integer that we increment with each update.
+ </p>
+ <p>
+ To determine the generation of the data you're using, when you initially
+ identify the area IDs look at the <code>generation-high</code> and
+ <code>generation-low</code> values MapIt is returning. For example,
+ here's the global MapIt data for
+ <a href="http://global.mapit.mysociety.org/point/4326/100.466667,13.75.html">a
+ point within Thailand</a> &mdash; the national border for Thailand is the
+ top level returned ("OSM Administrative Boundary Level 2"). Look on
+ that page for "Exists in generations" (or "<code>generation-</code>" in the
+ JSON data, available by changing MapIt's <code>.html</code> URL to <code>.json</code>)
+ to see the range of generations in which this area appears. You should
+ probably use the highest number (that is, the most recent update).
+ </p>
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ In this example, the whitelist contains a single area ID from global
+ MapIt's generation <code>4</code> for
+ <a href="http://global.mapit.mysociety.org/area/507455.html?generation=4">Thailand's national border</a>
+ (hence <code>507455</code> and
+ <a href="{{ "/glossary/#area-type" | relative_url }}" class="glossary__link">area type</a> <code>O02</code>):
+<pre>MAPIT_URL: http://global.mapit.mysociety.org/
+MAPIT_TYPES: ['O02']
+MAPIT_ID_WHITELIST: [507455]
+MAPIT_ID_GENERATION: 4
+</pre>
+ </li>
+ <li>
+ If you're not using a <code>MAPIT_ID_WHITELIST</code>
+ you usually don't need to specify a <code>MAPIT_ID_GENERATION</code>.
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="mapit_types_children"><code>MAPIT_TYPES_CHILDREN</code></a>
+ </dt>
+ <dd>
+ If your MapIt has the concept of council wards (subareas of councils, where
+ people can sign up for alerts, but not report things), then you can give the
+ MapIt type codes for them here.
+ <p>
+ You can leave this blank if your jurisidction doesn't use subareas.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ It's OK to leave this setting blank:
+ <p><code>MAPIT_TYPES_CHILDREN: ''</code></p>
+ </li>
+ <li>
+ In the UK we use something like:
+ <p><code>
+ MAPIT_TYPES_CHILDREN: [ 'DIW', 'LBW', 'MTW', 'UTE', 'UTW', 'CED', 'COP', 'LGW' ]
+ </code></p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="geocoder"><code>GEOCODER</code></a>
+ </dt>
+ <dd>
+ Which <a href="{{ "/glossary/#geocoder" | relative_url }}" class="glossary__link">geocoder service</a> to use to look up results, for
+ example, from front page "Enter your location" searches.
+ <p>
+ Possible choices are
+ <code>Google</code>, <code>Bing</code>, or <code>OSM</code>.
+ By default, FixMyStreet will use <code>OSM</code>, the
+ <a href="{{ "/glossary/#osm" | relative_url }}" class="glossary__link">OpenStreetMap</a>
+ geocoder.
+ </p>
+ <p>
+ For more information, see the
+ <a href="{{ "/customising/geocoder" | relative_url }}">page about geocoding</a>.
+ </p>
+ <p>
+ It's also possible to add a new geocoder (for example, if your
+ jurisdiction provides a custom one). This requires some coding work, but
+ you can see exampes of <a
+ href="https://github.com/mysociety/fixmystreet/tree/master/perllib/FixMyStreet/Geocode">supported geocoders</a> in the FixMyStreet repo.
+ </p>
+ <p>
+ Whichever geocoder you use, check the terms of use for it
+ &mdash; there may be restrictions. You may also need to provide an API
+ key to use it: see
+ <code><a href="#google_maps_api_key">GOOGLE_MAPS_API_KEY</a></code>
+ and
+ <code><a href="#bing_maps_api_key">BING_MAPS_API_KEY</a></code>.
+ </p>
+ <p>
+ See also <code><a href="#geocoding_disambiguation">GEOCODING_DISAMBIGUATION</a></code>
+ for restricting geocoder service to specific places.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ FixMyStreet defaults to <code>OSM</code> if you don't specify
+ a geocoder:
+ <p><code>GEOCODER: ''</code></p>
+ </li>
+ <li>
+ <code>GEOCODER: 'Bing'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="google_maps_api_key"><code>GOOGLE_MAPS_API_KEY</code></a> &amp;
+ <a name="bing_maps_api_key"><code>BING_MAPS_API_KEY</code></a>
+ </dt>
+ <dd>
+ If you wish to use Google Maps or Bing Maps Geocoding, get the
+ relevant key and set it here. See also the
+ <code><a href="#geocoder">GEOCODER</a></code> setting.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>
+ GOOGLE_MAPS_API_KEY: ''<br>
+ BING_MAPS_API_KEY: ''
+ </code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="geocoding_disambiguation"><code>GEOCODING_DISAMBIGUATION</code></a>
+ </dt>
+ <dd>
+ This setting provides parameters that are included in
+ <a href="{{ "/glossary/#geocoder" | relative_url }}" class="glossary__link">geocoding</a> requests, to hopefully
+ return more useful results. The options that will be applied vary depending
+ on which geocoder you are using (although unwanted options will be ignored,
+ so you can specify all of them, which might be convenient if you change
+ geocoder).
+ <p>
+ Remember that you specify which geocoder you are using with the
+ <code><a href="#geocoder">GEOCODER</a></code> setting.
+ </p>
+ <p>
+ For OSM, which is the default, you can use:
+ </p>
+<pre>
+GEOCODING_DISAMBIGUATION:
+ bounds: [ <em>&lt;min lat&gt;, &lt;min lon&gt;, &lt;max lat&gt;, &lt;max lon&gt;</em> ]
+ country: <em>&lt;country code to restrict results to&gt;</em>
+ town: <em>&lt;string added to geocoding requests if not already there&gt;</em>
+</pre>
+ <p>
+ If using Bing, you can use <code>town</code> and <code>bounds</code>, plus any of:
+ </p>
+<pre>
+ centre: "<em>&lt;lat&gt;&lt;lon&gt;</em>"
+ bing_culture: <em>&lt;culture code: see <a href="http://msdn.microsoft.com/en-us/library/hh441729.aspx">Bing docs</a>&gt;</em>
+ bing_country: <em>&lt;country name: only accept results that match this&gt;</em>
+</pre>
+ <p>
+ If using Google, you can use:
+ </p>
+<pre>
+ bounds: [ <em>&lt;min lat&gt;, &lt;min lon&gt;, &lt;max lat&gt;, &lt;max lon&gt;</em> ]
+ google_country: <em>&lt;.ccTLD to restrict results to&gt;</em>
+ lang: <em>&lt;language for results&gt;</em>
+</pre>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ This limits geocoding requests to only return results in Mumbai, India:
+<pre>
+GEOCODER: 'OSM'
+GEOCODING_DISAMBIGUATION:
+ country: 'in'
+ town: 'Mumbai'
+</pre>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="map_type"><code>MAP_TYPE</code></a>
+ </dt>
+ <dd>
+ The type of map you want to use. If left blank, the default is
+ <code>OSM</code> for
+ <a href="{{ "/glossary/#osm" | relative_url }}" class="glossary__link">OpenStreetMap</a>.
+ Other options are <code>GoogleOL</code> for Google Open Layers,
+ and other UK-specific values, including <code>FMS</code>
+ for UK <a href="https://www.fixmystreet.com">FixMyStreet</a>.
+ <p>
+ Check the usage terms for the type of map you use &mdash; there may be
+ restrictions.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>MAP_TYPE: 'OSM'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="allowed_cobrands"><code>ALLOWED_COBRANDS</code></a>
+ </dt>
+ <dd>
+ FixMyStreet uses a templating
+ <a href="{{ "/glossary/#cobrand" | relative_url }}" class="glossary__link">cobrand</a>
+ system to provide different looks (and behaviour) for
+ different installations. For example, if you create a cobrand
+ called <code>moon</code>, then FixMyStreet will look for templates in the
+ <code>templates/web/moon</code> directory and CSS in <code>web/cobrands/moon</code>. To make this work, set:
+<pre>
+ALLOWED_COBRANDS:
+ - moon
+</pre>
+ <p>
+ If you specify <em>only one</em> cobrand in this way, your FixMyStreet site will simply run using that cobrand (so that would be <code>moon</code> in the example above). This is probably all you need!
+ </p>
+ <p>
+ However, it is possible for a FixMyStreet site to support <em>more than
+ one cobrand at the same time</em>. <strong>Most installations don't need
+ this</strong>, but if yours does, it's very useful: the server decides
+ which cobrand to use by inspecting the hostname of the incoming request.
+ </p>
+ <p>
+ If you wish to use multiple cobrands, specify them in a list, optionally
+ with hostname-matching regular expressions if the name of the cobrand is
+ not enough. If the hostname of the current request does not match with
+ any in the list, FixMyStreet will use the Default cobrand. For example:
+ </p>
+<pre>
+ALLOWED_COBRANDS:
+ - moon
+ - venus
+</pre>
+ <p>
+ Any hostname with "<code>moon</code>" in it will use the moon cobrand
+ (for example, <code>fixmymoon.org</code>), any with "<code>venus</code>"
+ will use the venus cobrand. Anything else (such as
+ <code>www.example.com</code>, which contains neither "<code>moon</code>"
+ nor "<code>venus</code>") will use the Default cobrand.
+ </p>
+ <p>
+ Instead of using the cobrand's name as the matching string, you can
+ specify an alternative string to match on (in fact, the string can be a
+ regular expression):
+ </p>
+<pre>
+ALLOWED_COBRANDS:
+ - moon: 'orbital'
+ - venus
+</pre>
+ <p>
+ Here, any hostname with "<code>orbital</code>" in it will use the moon
+ cobrand. Conversely, a request to <code>www.fixmymoon.org</code> won't
+ match anything, so it would be served with the Default cobrand instead.
+ This also allows development servers to map to different cobrands if
+ needed, using DNS subdomains, for example.
+ </p>
+ <p>
+ If you're running a site with multiple cobrands, you'll never want to
+ serve the Default cobrand on your
+ <a href="{{ "/glossary/#production" | relative_url }}" class="glossary__link">production</a>
+ server, so make sure you've set ALLOWED_COBRANDS correctly.
+ </p>
+ <div class="more-info">
+ <p>Examples:</p>
+ <ul class="examples">
+ <li>
+ <p>
+ Note that specifying <em>a single allowed cobrand</em> is a
+ special, simple case: FixMyStreet will always use the
+ <code>mycobrand</code>. This is probably all you need!
+ </p>
+<pre>
+ALLOWED_COBRANDS:
+ - mycobrand
+</pre>
+ </li>
+ <li>
+ <p>
+ If there's more than one allowed cobrand, FixMyStreet uses string
+ matching (described above) on the hostname to determine which one
+ to use:
+ </p>
+<pre>
+ALLOWED_COBRANDS:
+ - cobrand1
+ - cobrand2: 'hostname_substring2'
+ - cobrand3
+</pre>
+ <p>
+ Make sure you've covered everything, because any requests to a
+ hostname that don't match will be served using the Default cobrand,
+ which isn't what you want.
+ </p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="admin_base_url"><code>ADMIN_BASE_URL</code></a>
+ </dt>
+ <dd>
+ This is used in "offensive report" emails to provide a link directly
+ to the admin interface, and to make sure the admin can work through a
+ proxy. It defaults to `/admin` in your installation.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>ADMIN_BASE_URL: ''</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="rss_limit"><code>RSS_LIMIT</code></a>
+ </dt>
+ <dd>
+ How many items are returned in the GeoRSS feeds?
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>RSS_LIMIT: '20'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="open311_limit"><code>OPEN311_LIMIT</code></a>
+ </dt>
+ <dd>
+ How many items are returned by default in an Open311 response?
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>OPEN311_LIMIT: 100</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="all_reports_per_page"><code>ALL_REPORTS_PER_PAGE</code></a>
+ </dt>
+ <dd>
+ How many reports to show per page on the <em>All Reports</em> pages?
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>ALL_REPORTS_PER_PAGE: 100</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="smtp_smarthost"><code>SMTP_SMARTHOST</code></a>
+ </dt>
+ <dd>
+ The default SMTP smarthost is <code>localhost</code>, a mail server on the
+ same machine you are running FixMyStreet. If you wish to send email through
+ a SMTP server elsewhere, change this and the other SMTP settings.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>SMTP_SMARTHOST: 'localhost'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+ <dt>
+ <a name="smtp_type"><code>SMTP_TYPE</code></a>
+ </dt>
+ <dd>
+ If your SMTP server supports SSL or TLS, set this variable to 'ssl' or
+ 'tls', otherwise leave it as '' for unencrypted SMTP.
+ </dd>
+ <dt>
+ <a name="smtp_port"><code>SMTP_PORT</code></a>
+ </dt>
+ <dd>
+ The default SMTP port is 25 for unencrypted, 465 for SSL and 587 for TLS.
+ Leave as '' to use the default, otherwise set to your SMTP server port.
+ </dd>
+ <dt>
+ <a name="smtp_username"><code>SMTP_USERNAME</code></a>
+ </dt>
+ <dd>
+ The username for authenticating with your SMTP server, if required.
+ </dd>
+ <dt>
+ <a name="smtp_password"><code>SMTP_PASSWORD</code></a>
+ </dt>
+ <dd>
+ The password for authenticating with your SMTP server, if required.
+ </dd>
+
+ <dt>
+ <a name="area_links_from_problems"><code>AREA_LINKS_FROM_PROBLEMS</code></a>
+ </dt>
+ <dd>
+ Should problem reports link to the council summary pages? Set to <code>0</code> to disable, or <code>1</code> to enable.
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ Disable links to the summary page:
+ <p><code>AREA_LINKS_FROM_PROBLEMS: '0'</code></p>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="gaze_url"><code>GAZE_URL</code></a>
+ </dt>
+ <dd>
+ Gaze is a world-wide service for population density lookups. You can leave
+ this as is. It is used to provide the default radius for email/RSS alerts
+ and to set the default zoom level on a map page (so in rural areas, you're
+ more likely to get a slightly more zoomed out map).
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>GAZE_URL: 'https://gaze.mysociety.org/gaze'</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+ <dt>
+ <a name="message_manager_url"><code>MESSAGE_MANAGER_URL</code></a>
+ </dt>
+ <dd>
+ If you're using <a href="https://github.com/mysociety/message-manager/">Message Manager</a>,
+ integrated with an SMS gateway, include the URL here. FixMyStreet does
+ not usually use this, so you can leave it blank.
+ <p>
+ Providing a URL does not automatically enable the service &mdash; your <a
+ href="{{ "/glossary/#cobrand" | relative_url }}" class="glossary__link">cobrand</a>
+ must be explicitly coded to use it. Contact us if you need to use Message
+ Manager with your FixMyStreet site.
+ </p>
+ <div class="more-info">
+ <p>Example:</p>
+ <ul class="examples">
+ <li>
+ <code>MESSAGE_MANAGER_URL: ''</code>
+ </li>
+ </ul>
+ </div>
+ </dd>
+
+</dl>
diff --git a/docs/customising/css.md b/docs/customising/css.md
new file mode 100644
index 000000000..c41d5b411
--- /dev/null
+++ b/docs/customising/css.md
@@ -0,0 +1,322 @@
+---
+layout: page
+title: Customising the design
+author: dave
+---
+
+# Customising the design
+
+<p class="lead">
+ This page describes how to change the directionality and colour scheme of
+ your installation &mdash; which is a good starting point for further
+ customisations.
+</p>
+
+## Background
+
+The CSS is stored in `web/cobrands/` under which there are directories for
+Cobrands. Note that FixMyStreet uses SCSS and Compass to generate its CSS so
+there are no CSS files until `bin/make_css` has been run as the site user.
+
+The CSS provided with FixMyStreet uses CSS3 media queries in a mobile-first
+format order to adapt the layout to work on different devices. It is structured
+into these main files:
+
+* `base.css` --
+ all the styling for the content of the pages in a mobile sized browser.
+* `layout.css` --
+ all the styling for the content of the pages in a desktop sized browser.
+* `_colours.css` --
+ basic settings information, so you can easily make a site that
+ looks different simply by copying these files to your own cobrand CSS
+ directory, and changing the contents, as we will describe below.
+
+Our `.gitignore` file assumes that any CSS files directly in a `cobrands/*`
+directory are generated from SCSS - if you have CSS files that you want to use
+directly, put them in a `css` directory within your cobrand directory.
+
+# Tutorial
+
+You can override any of the CSS or HTML templates of your FixMyStreet
+installation, but to begin with it's a good idea to just change the colours.
+That way you can learn how FixMyStreet customisation works, before tackling
+more complex layout, design, or code changes.
+
+## Start simple!
+
+FixMyStreet's default CSS comes with a few basic colour settings which you can
+change. Remember that ultimately **you can override any styling for your own
+site** but most of this page shows how to set your own colours *without adding
+any new HTML or CSS*. We know that you'll want to change more than just the
+default colours: but this is the best way to start.
+
+Once you've done this, you'll have your own <a href="{{ "/glossary/#cobrand" | relative_url }}"
+class="glossary__link">cobrand</a>, and can start changing other stylesheets and
+templates in the same way.
+
+
+## Why you should create a cobrand
+
+A cobrand is just FixMyStreet's way of separating your customisation from
+everybody else's. To start with, this is almost as simple as putting what you
+need in its own directory.
+
+<div class="attention-box warning">
+ You <em>can</em> simply edit the default settings (just edit the values in
+ <code>web/cobrands/default/_colours.scss</code> and run
+ <code>bin/make_css</code>) but we <strong>strongly recommend</strong> you do
+ not do that. It's OK if you just want to play with the settings to see what's
+ possible, but the right way to change how your site looks is to make a
+ cobrand.
+</div>
+
+By making your own cobrand you'll be keeping your changes separate from the
+core code, but also keeping it within the main repository. This has serious
+benefits later on: it means you can easily update the FixMyStreet code (we
+frequently add new features, for example) while retaining your changes.
+
+
+## How to change the colours
+
+
+This is the process:
+
+1. pick a name for your cobrand
+2. update your config to use the new cobrand
+3. create a directory for it in `web/cobrands`
+4. copy the default cobrand's CSS into it
+5. edit the colours
+6. run `bin/make_css`
+
+
+The rest of this page describes each step in detail.
+
+
+### Pick a name for your cobrand
+
+Choose a name for your cobrand. In the examples below, we've used `fixmypark`,
+but you can use anything provided it's not a cobrand already in use in the
+code. Only use lower case letters. This name is never seen by the public &mdash;
+it's FixMyStreet's internal name for it.
+
+### Update your config to use the new cobrand
+
+You need to tell FixMyStreet to use your cobrand instead of the default one.
+
+FixMyStreet uses the
+<code><a href="{{ "/customising/config/#allowed_cobrands" | relative_url }}">ALLOWED_COBRANDS</a></code>
+config variable to decide which cobrand to use. In `conf/general.yml`, set it to your new cobrand like this:
+
+ ALLOWED_COBRANDS:
+ - fixmypark
+
+In fact, `ALLOWED_COBRANDS` is
+[a little more complex that it looks]({{ "/customising/config/#allowed_cobrands" | relative_url }}).
+If you give it a list of cobrands, it will decide which one to use depending on string
+matches on the incoming URL *for every request* But for most cases you don't want it to switch.
+So if you just specify just one cobrand like this, FixMyStreet will simply use it.
+
+### Create a directory for your cobrand in web/cobrands
+
+Make a new directory with your cobrand's name in `web/cobrands/` For example,
+on the command line, do:
+
+ cd fixmystreet
+ mkdir web/cobrands/fixmypark
+
+
+### Copy the default cobrand's CSS into yours
+
+Copy the contents of `web/cobrands/default` into that directory.
+
+ cp web/cobands/default/* web/cobrands/fixmypark
+
+This puts the stylesheet files you need into your cobrand.
+At this point, your cobrand is effectively a copy of the default one.
+
+### Edit the colours
+
+The default cobrand's colour scheme, which you have copied, will be blue and
+orange &mdash; we picked startling colours to force people to want to customise it.
+
+We use SCSS (instead of CSS) because it's a more powerful way of defining and
+managing styles. This means that when you make any changes, FixMyStreet needs
+to compile those SCSS files to rebuild the CSS &mdash; see the following
+section.
+
+You can edit the colours defined in `web/cobrands/fixmypark/_colours.scss`.
+You'll need to use [web colour
+codes](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Co
+lor) to specify the colours you want.
+
+Be careful: if you're not familiar with SCSS, the syntax of that file is a
+little strict. Typically, those colours *must* always be either exactly three
+or six hex characters long. And there must be a `#` before and a semicolon after each one.
+
+These are the colours which you can easily change within your copy of the
+stylesheet:
+
+<table class="table">
+ <tr>
+ <th>
+ variable
+ </th>
+ <th>
+ examples of where it's used in the default cobrand
+ </th>
+ </tr>
+ <tr>
+ <td>
+ <code>$primary</code>
+ </td>
+ <td>
+ the front page's main banner background
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$primary_b</code>
+ </td>
+ <td>
+ border around the the front page street/area input
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$primary_text</code>
+ </td>
+ <td>
+ text on the front page banner
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$base_bg</code><br>
+ <code>$base_fg</code>
+ </td>
+ <td>
+ Large width page background/foreground (bleeding to edge)
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$map_nav_bg</code><br>
+ <code>$nav_fg</code>
+ </td>
+ <td>
+ Mobile width, the header's colours; large width, the navigation's
+ foreground colour
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$menu-image</code>
+ </td>
+ <td>
+ “Hamburger” menu colour (<code>menu-black</code> or
+ <code>menu-white</code>)
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$col_click_map</code><br>
+ </td>
+ <td>
+ background of the "click map to report problem" banner on the
+ map page
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$col_fixed_label</code><br>
+ <code>$col_fixed_label_dark</code>
+ </td>
+ <td>
+ background of the colour of the "fixed" label that appears on
+ fixed reports, and its darker underside
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <code>$col_big_numbers</code>
+ </td>
+ <td>
+ Colour to use for the step numbers on the front page.
+ </td>
+ </tr>
+</table>
+
+SCSS supports functions such as `darken` so you can specify colours that are
+calculated from other colours like this:
+
+ $col_click_map: #ee6040;
+ $col_click_map_dark: darken($col_click_map, 10%);
+
+For more about SCSS, see [the SASS website](http://sass-lang.com).
+
+
+### Run make_css so FixMyStreet's CSS uses the new values
+
+FixMyStreet now needs to absorb those changes by rebuilding the CSS. There's a
+task in the `bin` directory called `make_css` that will do this for you. You'll
+need to be logged into your shell in the `fixmystreet` directory as the site
+user, then do:
+
+ bin/make_css
+
+This will update the CSS files. You can run the command just for your cobrand
+by specifying the path to your cobrand’s SCSS as an argument, e.g.:
+
+ bin/make_css web/cobrands/fixmypark
+
+Keep an eye on the output of that command &mdash; if there's a problem (for
+example, if you've made a mistake in the SCSS syntax, which is easy to do), it
+will report it here.
+
+
+### See the new colours
+
+If you look at your site in a browser, you'll see the new colours. Remember
+that every time you edit them, you need to run `bin/make_css` to make
+FixMyStreet include the changes, or run `bin/make_css --watch` to have it
+monitor for changes itself.
+
+
+## Or... use your own CSS and HTML
+
+Remember that *all* you've done here is change the colours, **using the
+existing default CSS and HTML**. Of course any and all of this can be
+overridden (by overriding CSS files and overriding the bits of HTML that you
+want to change in the <a href="{{ "/glossary/#template" | relative_url }}"
+class="glossary__link">templates</a>) but this is just so you can get going.
+
+# Directionality
+
+If you wish to use FixMyStreet in a right-to-left layout, this is very
+straightforward and involves two steps:
+
+* First, uncomment the line in your cobrand’s `_colours.scss` file as explained,
+ so that the `$direction` variable is set to `right`.
+* Secondly, create a copy of the `templates/web/base/header.html` in
+ your own cobrand if you haven’t already (see
+ [template customising]({{ "/customising/templates/" | relative_url }}) for more
+ details) and uncomment the `SET` line that sets `dir="rtl"`.
+
+That’s it; recompile your CSS, reload your site and you will find that
+FixMyStreet has switched to a right-to-left layout. Your next step will
+probably be to [change the language]({{ "/customising/language/" | relative_url }})
+used by your site.
+
+# Next steps...
+
+If you want to customise the logo, [we have a tutorial for that](../logo/).
+
+Now you have your own cobrand, adding your own HTML <a
+href="{{ "/glossary/#template" | relative_url }}" class="glossary__link">templates</a> is straightforward.
+
+Please see our separate page on [customising templates]({{ "/customising/templates/" | relative_url }}).
+
+### Feeding back changes
+
+Finally, when you've finished creating your cobrand you should consider
+[feeding it back to us]({{ "/feeding-back" | relative_url }}) so it becomes part of the FixMyStreet repository.
diff --git a/docs/customising/fms_and_mapit.md b/docs/customising/fms_and_mapit.md
new file mode 100644
index 000000000..c02609404
--- /dev/null
+++ b/docs/customising/fms_and_mapit.md
@@ -0,0 +1,63 @@
+---
+layout: page
+title: How FixMyStreet assigns reports to bodies
+author: dave
+---
+
+# How FixMyStreet assigns reports to bodies
+
+<p class="lead">
+ When you add a <a href="{{ "/glossary/#body" | relative_url }}" class="glossary__link">body</a>
+ to FixMyStreet, you specify which <a href="{{ "/glossary/#area" | relative_url }}" class="glossary__link">areas</a>
+ it covers. The areas are typically defined by administrative boundaries: these
+ are <em>not</em> part of FixMyStreet, but are made available through our
+ service called <a href="{{ "/glossary/#mapit" | relative_url }}" class="glossary__link">MapIt</a>.
+</p>
+
+Note that MapIt tells FixMyStreet what administrative boundaries a point lies
+within: it does not actually draw the maps (by default, FixMyStreet uses
+<a href="{{ "/glossary/#osm" | relative_url }}" class="glossary__link">OpenStreetMap</a> for that).
+
+## How this works
+
+When someone places a pin on the FixMyStreet
+<a href="{{ "/glossary/#map" | relative_url }}" class="glossary__link">map</a>
+to report a problem, FixMyStreet sends the
+<a href="{{ "/glossary/#latlong" | relative_url }}" class="glossary__link">lat-long</a>
+coordinates of that position to MapIt. MapIt responds with a list of the areas
+that the pin lies within. FixMyStreet then looks in its own database to find
+all the bodies that cover that area, and the
+<a href="{{ "/glossary/#contact" | relative_url }}" class="glossary__link">contacts</a>
+(which are usually email addresses) that you have added for each of
+those bodies. Because each contact is associated with a
+<a href="{{ "/glossary/#category" | relative_url }}" class="glossary__link">category</a>
+of problem (for example, "Potholes" or "Graffiti"), FixMyStreet can build a
+list of all the problem categories that *can* be reported at this location. In
+fact, this list appears as the drop-down menu ("Pick a category") on the
+report-a-problem page.
+
+This means that your FixMyStreet installation must be able to connect to a
+MapIt service which knows about the administrative boundaries in your part of the
+world. [See below](#boundaries) for more about setting this up.
+
+## Detailed flow: location &rarr; map pin &rarr; drop-down menu
+
+![FMS bodies and contacts]({{ "/assets/img/fms_bodies_and_contacts.png" | relative_url }})
+
+<a name="boundaries"> </a>
+
+## How to set up the area boundaries
+
+The type of boundary data you need depends on a number of factors, but will
+probably be one of these:
+
+ * ["Everywhere"]({{ "/customising/boundaries/#everywhere" | relative_url }}) -- you can run FixMyStreet without a specific boundary
+ * [Simple approximate area]({{ "/customising/boundaries/#approx-area" | relative_url }}) -- that is, just one area around the place you need
+ * [Simple approximate areas]({{ "/customising/boundaries/#approx-areas" | relative_url }}) -- as above, but for multiple areas
+ * [Accurate OpenStreetMap data]({{ "/customising/boundaries/#mysociety-mapit" | relative_url }}) -- the preferred option
+ * [Accurate data that isn't on OSM]({{ "/customising/boundaries/#accurate" | relative_url }}) -- if you have your own boundary data, for example
+
+If you're not sure which is for you, read through the
+[whole page about admin boundaries]({{ "/customising/boundaries/" | relative_url }}).
+
+
diff --git a/docs/customising/geocoder.md b/docs/customising/geocoder.md
new file mode 100644
index 000000000..4dc44b507
--- /dev/null
+++ b/docs/customising/geocoder.md
@@ -0,0 +1,35 @@
+---
+layout: page
+title: How to customise the geocoder
+author: matthew
+---
+
+# How to customise the FixMyStreet geocoder
+
+<p class="lead">
+ The first step of using FixMyStreet is entering a string
+ that the needs to be <em>geocoded</em> to take you to a relevant map page.
+</p>
+
+See the diagram below for the full flow of using FixMyStreet. The geocoder is
+near the start of the process, before maps, MapIt boundaries or bodies enter
+the picture.
+
+The geocoder takes a string -- for example, the name of a place or a street --
+and converts it into a [lat-long]({{ "/glossary/#latlong" | relative_url }}) location.
+
+The geocoder defaults to OpenStreetMap's [Nominatim](http://nominatim.openstreetmap.org).
+FixMyStreet also contains Bing and Google based geocoders, and can use
+custom geocoders too.
+
+You can customise the geocoding by providing limiting parameters in
+<code><a href="{{ "/customising/config/#geocoding_disambiguation" | relative_url }}">GEOCODING_DISAMBIGUATION</a></code>.
+You typically need to do this so the geocoder only considers places in the area
+your FixMyStreet site is serving. For example, you may want to limit results to
+a specific country or city.
+
+The options vary [depending on which geocoder you use]({{ "/customising/config/#geocoding_disambiguation" | relative_url }}).
+
+## Detailed flow: location &rarr; map pin &rarr; drop-down menu
+
+![FMS bodies and contacts](/assets/img/fms_bodies_and_contacts.png)
diff --git a/docs/customising/index.md b/docs/customising/index.md
new file mode 100644
index 000000000..610e44ae3
--- /dev/null
+++ b/docs/customising/index.md
@@ -0,0 +1,82 @@
+---
+layout: page
+title: Customising
+---
+
+# Customising FixMyStreet
+
+<p class="lead">
+ When you set up your FixMyStreet site, you'll want to tailor the
+ default installation to your own requirements. This includes limiting
+ the geographic area it will accept problem reports for, the language
+ it's presented in, and how it looks.
+</p>
+
+
+## Your own cobrand
+
+Whatever you change, you'll almost certainly need to create a
+<a href="{{ "/glossary/#cobrand" | relative_url }}" class="glossary__link">cobrand</a>,
+which is the mechanism FixMyStreet uses to let you deviate from its default
+appearance and behaviour.
+
+As well as the
+[configuration settings]({{ "/customising/config/" | relative_url }}) you specify in
+the `conf/general.yml` file, a cobrand is made up of a set of templates, CSS,
+and an *optional* Cobrand module that contains custom Perl code. There are
+defaults for all of these, so the cobrand only needs to override things that are
+specific to it.
+
+We *strongly recommend* you follow this system -- rather than just editing
+existing files -- because it means that you'll be able to upgrade FixMyStreet
+without the updates overwriting your unique changes.
+
+It's a good idea for a cobrand to have the same name as your site. For example,
+if your site is `www.FixMyPark.com` then your cobrand could be called FixMyPark
+(with the "moniker" all lowercase, like this: `fixmypark`, which is used for
+things like directory names). The default cobrand is called Default (`default`).
+
+
+## What you can change
+
+There's a lot you can customise on your own FixMyStreet site.
+
+We've prepared a [customisation checklist]({{ "/customising/checklist/" | relative_url }})
+which covers all the key things you should work through when installing your own
+site.
+
+But if you just want to see what's possible, here are some of the
+aspects of FixMyStreet that you can customise:
+
+* [how to translate or change FixMyStreet's language]({{ "/customising/language/" | relative_url }})
+* [how FixMyStreet assigns reports to bodies]({{ "/customising/fms_and_mapit/" | relative_url }})
+* [how to customise the geocoder]({{ "/customising/geocoder/" | relative_url }})
+* [how to change the design]({{ "/customising/css/" | relative_url }})
+* [how to customise templates]({{ "/customising/templates/" | relative_url }})
+* [how reports are sent by FixMyStreet]({{ "/customising/send_reports/" | relative_url }})
+* [all the config settings]({{ "/customising/config/" | relative_url }})
+
+Note that none of the above require you to know or write any Perl (the language
+FixMyStreet is mostly written in).
+
+### The Cobrand module
+
+If you need more customistation than the config settings and templates give you,
+you'll probably need to make a Cobrand module. This is a Perl module that is automatically
+loaded according to the current cobrand -- you can see existing examples in
+[`perllib/FixMyStreet/Cobrand/`](https://github.com/mysociety/fixmystreet/tree/master/perllib/FixMyStreet/Cobrand).
+There is a default Cobrand
+([`Default.pm`](https://github.com/mysociety/fixmystreet/blob/master/perllib/FixMyStreet/Cobrand/Default.pm))
+that all Cobrands should inherit from. A Cobrand module can then override any
+of the methods from the default Cobrand.
+See [more about Cobrand modules](/customising/cobrand-module/).
+
+## Feeding back changes
+
+It would be great if the changes you make to the code could be fed back
+upstream to benefit other users. Obviously if you've only customised templates
+and CSS you may not feel you have to, but it's likely you'll have needed to
+make actual code changes for your particular environment, and feeding these
+back means it is easier to update the code from upstream in future to gain new
+features and bugfixes.
+See [more about feeding back changes]({{ "/feeding-back/" | relative_url }}).
diff --git a/docs/customising/integration.md b/docs/customising/integration.md
new file mode 100644
index 000000000..95806a039
--- /dev/null
+++ b/docs/customising/integration.md
@@ -0,0 +1,228 @@
+---
+layout: page
+title: Integration
+author: dave
+---
+
+# Integrating FixMyStreet with back-end systems
+
+<p class="lead">
+ By default, FixMyStreet uses email to send problem reports to the body
+ responsible for fixing them. But it's best if sending reports is
+ <strong>integrated</strong> directly, so that problems are injected directly
+ into the body's back-end system.
+</p>
+
+## Integrate if you can!
+
+Often <a href="{{ "/glossary/#body" | relative_url }}" class="glossary__link">bodies</a>,
+especially if they are local government bodies, already have databases and
+back-end systems for tracking problems they are fixing. FixMyStreet works fine
+if you just use the default <a href="{{ "/glossary/#send-method" | relative_url }}"
+class="glossary__link">send method</a>, which is email, but it's *much better* if you
+can integrate with the body's back-end systems.
+
+How hard this is depends on the kind of system the body is using, and how much
+cooperation they offer FixMyStreet. In general, once FixMyStreet is integrated
+it's *easier* for the body's staff to use.
+
+Our experience with FixMyStreet in the UK is that councils that integrate with
+FixMyStreet also choose to run it as a <a href="{{ "/glossary/#cobrand" | relative_url }}"
+class="glossary__link">cobrand</a> (that is, branded and on their own website). In
+fact, cobranding and integrating are not dependent on each other, so if you do
+one it is not necessary to do the other.
+
+## Levels of integration (and their benefits)
+
+<ol start="0">
+ <li>
+ <strong>no integration</strong> (the default)<br>
+ reports are sent by email
+ </li>
+ <li>
+ <strong>reports are injected directly into the back-end</strong>
+ <br>
+ so staff don't have to copy-and-paste from emails &mdash; furthermore,
+ if the body returns its own reference for the report, then FixMyStreet
+ can publish it
+ </li>
+ <li>
+ <strong>status changes on the back-end propogate to FixMyStreet</strong>
+ <br>
+ so staff don't have to log in to FixMyStreet and mark
+ problems as "fixed" by hand... and FixMyStreet publicises the
+ work that the authorities are doing
+ </li>
+ <li>
+ <strong>problems created in the back-end appear on FixMyStreet</strong>
+ <br>
+ so all the problems the body is working on are public
+ </li>
+</ol>
+
+Although you can approach each of these levels of integration as custom
+programming tasks, we *strongly recommend* you use the
+<a href="{{ "/glossary/#open311" | relative_url }}" class="glossary__link">Open311</a>
+open standard when you can.
+
+Strictly speaking it's possible to implement any of these levels independently
+of the others. In practice, though, each one tends to follow on from the
+previous one.
+
+## You don't need to integrate *everything*
+
+You can integrate with just one body (while the others continue to use email).
+You can even just integrate certain
+<a href="{{ "/glossary/#category" | relative_url }}" class="glossary__link">categories</a>
+for a body &mdash; for example, "Potholes" and "Fallen trees" could be
+submitted by Open311, while "Streetlighting" problems are sent by email.
+
+## No integration: send reports by email
+
+With **no integration**, problem reports are sent by email:
+
+<img src="/assets/img/fms_integration_0.png">
+
+
+## Stage 1: Injecting directly into the back-end
+
+With the **first level of integration**, problem reports are injected directly
+into back-end:
+
+<img src="/assets/img/fms_integration_1.png">
+
+
+If the body's server is already <a href="{{ "/glossary/#open311" | relative_url }}"
+class="glossary__link">Open311</a> compliant, you can switch on the first stage
+of integration -- which puts the problem report directly into the body's
+back-end system instead of emailing it -- just by setting the send method (for
+the body, or for specific categories) to Open311.
+
+To enable Open311 for a body, edit in in the admin and set **send method** to
+"Open311". A form will appear for Open311 connection details including, for
+example, the body's endpoint URL. It's common for Open311 endpoints to require
+an API key and possibly access criteria before they will accept Open311 service
+requests. You'll probably need to talk to the body's IT team to be granted
+access -- for example, they may only open a port to your server's single IP
+address.
+
+If you want to have the problem reports for some categories to be integrated
+into their body's back-end, but continue to send others by email, you can
+<a href="{{ "/glossary/#devolve" | relative_url }}"
+class="glossary__link">devolve</a>
+choosing the send method to the contacts. Set the body's send method as above,
+but also enable **contacts can be devolved**. Now you can set specific
+contacts' *send methods* to `email`, which will override the body's send method.
+
+### Passing external IDs between the two systems
+
+When a problem report is successfully posted to the body over Open311, usually
+the back-end responds with the body's reference. FixMyStreet stores this in the
+`problem` record as the `external_id` (because from FixMyStreet's point of view,
+the back-end is the external system).
+
+In our experience, bodies integrated in this way often want to know the
+FixMyStreet ID for the report, to store at their end. From the body's point of
+view, FixMyStreet is the external system, so we usually pass this to them in
+the Open311 POST request as `attribute[fixmystreet_id]`. If the body sets up
+their Open311 server to request this attribute, we will automatically fill it.
+If they want the field named differently, you will need to store it as the
+`id_field` extra metadata on the relevant contacts.
+
+### What if the back-end system is not Open311 compliant?
+
+If the body you want to integrate with does not yet support the Open311 standard,
+you can still integrate with it, but it takes a little more work. If the back-end
+offers an alternative way to post new problem reports into it, then you'll need to
+code it. Typically this could involve either adding a custom Perl module to
+`perlib/FixMyStreet/SendReport`, or writing a 'proxy' server that receives Open311
+data from FixMyStreet (so it *is* Open311 from FixMyStreet's point of view) and
+then sends on differently formatted data elsewhere.
+
+We *strongly recommend* you try to implement the Open311 standard instead, but
+you might well not be able to change the back-end system (often these are
+large, proprietary and inflexible systems), so you may be able to implement a
+shim that makes it behave like one. For example, in the UK we integrate with a
+number of councils whose back-end does not use the Open311 standard, by running
+a script either on our or their server, which accepts incoming Open311 requests
+and converts them into custom calls. The script captures the result and sends
+it back as the appropriate Open311 response. We have an
+[example](https://github.com/mysociety/open311-adapter) of one adapter we use
+on GitHub.
+
+The advantage of this approach is that, to FixMyStreet, the body uses the tried
+and tested Open311 send method. The benefit to the body is that should their
+back-end one day implement the Open311 standard, or they change to using one that
+does, then no changes will be necessary other than to remove the scripts.
+
+
+## Stage 2: Automatically updating problem statuses
+
+With the **second level of integration**, not only are reports injected
+directly into the back-end, but back-end status changes automatically propogate
+*back* to FixMyStreet:
+
+<img src="/assets/img/fms_integration_2.png">
+
+When the body fixes a problem, they mark it as fixed in their back-end system.
+Stage 2 integration detects this change and automatically updates the record
+on FixMyStreet. Typically this means marking the problem as fixed (turning the
+pin green, if configured to do so) and optionally adding a description from the
+council.
+
+A basic form of this is in the Open311 standard, but we prefer a slight extension
+(which we think should be: see [this
+explanation](https://www.mysociety.org/2013/02/20/open311-extended/)) and it
+requires the back-end to expose update data.
+
+Our experience is that most back-ends do not already provide this data, but that
+it is a relatively easy for them to implement if they choose to do so. For
+example, on a typical problem database, one method is to add a trigger that
+detects whenever the status of a problem changes (for example, is marked as
+fixed), and record the time and status change in a new table. FixMyStreet polls
+the back-end for updates within certain time bounds ("have any problems' statuses
+changed in the last 15 minutes?"), which effectively reads from
+this new table.
+
+FixMyStreet adds these changes automatically as updates on the public site: for
+example, marking a problem as fixed with either a custom comment send from the
+back-end or else a boilerplate one (for example, "Fixed by Borsetshire Council
+road crew").
+
+In order to set this up you first need to liaise with the body to make the
+update data available. You can then enable it by editing the body in the admin,
+and enabling **Open311 update-sending**. You also need to nominate a FixMyStreet
+user to which all these updates will be credited (for example, "Borsetshire
+Council") -- if necessary you can create a user just for this purpose at
+`/admin/users`.
+
+The mechanism we use for propogating fixes (and other status changes) from the
+back-end to the FixMyStreet site is deliberately light on the body. That is,
+once the body has implemented the update table (or its equivalent), FixMyStreet
+is responsible for polling the back-end -- there's no requirement for the body's
+system to do anything other than respond to these requests. Furthermore, when it
+does so, it uses the back-end's own reference (stored in FixMyStreet's database
+as the `external_id`) to identify problem reports, so there is no requirement
+to use the FixMyStreet ID. Because FixMyStreet polls regularly (typically
+every 15 minutes thoughout the day, with a single 24-hour mop-up once during
+the night), any problems connecting or tracking which updates have been picked
+up are handled at the FixMyStreet end.
+
+## Stage 3: Displaying problems not originating on FixMyStreet
+
+With the **third level of integration**, problems reported by staff on the
+back-end are shown on FixMyStreet too:
+
+<img src="/assets/img/fms_integration_3.png">
+
+The third level of integration is for *all* problem reports on the back-end to be
+displayed on the FixMyStreet system. Before doing this, you need to consider:
+
+ * how the body decides which, if any, reports should be excluded
+ * importing existing records (typically a big batch job, since there may be very many)
+ * ensuring imported categories all match
+ * ongoing acquisition of new records as they are added (feasible using Open311)
+
+Talk to us before doing this level of integration. Our experience is that levels
+1 and 2 are higher priority both for public users and for the authorities, so it's
+a good idea to implement those first.
diff --git a/docs/customising/language/index.md b/docs/customising/language/index.md
new file mode 100644
index 000000000..17cfec27b
--- /dev/null
+++ b/docs/customising/language/index.md
@@ -0,0 +1,140 @@
+---
+layout: page
+title: Changing the language
+---
+
+# Changing the language
+
+<p class="lead">Here we explain how to change what language is displayed on
+FixMyStreet, how to contribute your own if we don&rsquo;t have yours, and how to
+run a site in multiple languages.</p>
+
+## Setup
+
+The translations for most FixMyStreet strings are stored as standard
+<a href="{{ "/glossary/#gettext" | relative_url }}" class="glossary__link">gettext</a>
+files, in `FixMyStreet.po` files under `locale/<lang>/LC_MESSAGES/`. A
+few full pages, such as the FAQ, and emails, are stored separately in the
+templates directory and should be translated by creating new templates in your
+cobrand.
+
+
+Firstly, set the
+<code><a href="{{ "/customising/config/#languages" | relative_url }}">LANGUAGES</a></code>
+configuration option to the languages your site uses. This is an array of
+strings specifying what language or languages your installation uses. For
+example, if your site is available in English, French, and German, you would
+have:
+
+ LANGUAGES:
+ - 'en-gb,English,en_GB'
+ - 'fr,French,fr_FR'
+ - 'de,German,de_DE'
+
+This would then set up things appropriately to use the relevant language files
+you have made.
+
+You must make sure that the locale for any language you use is installed on the
+server in order for the translations to work properly. On Debian, you can alter
+`/etc/locale.gen` and run `sudo locale-gen`. On Ubuntu, you can just run `sudo
+locale-gen <LOCALE_NAME>`.
+
+## Seeing the site in your language
+
+By default, FixMyStreet is set up so visiting a hostname starting with the
+two-letter language code will use that language; otherwise it will detect based
+upon the browser. If you have used the install script on a clean server, or the
+AMI, you should be able to visit your domain with a language code at the start
+by default.
+
+Using the example above `http://fr.fixmystreet.com/` would display the
+French translation and `http://de.fixmystreet.com/` would display the
+German translation. If no language is specified in the URL, or an
+unsupported code is used then it will fall back to the language
+negotiated by the browser. If that language is not available,
+the first language listed in the `LANGUAGES` configuration option
+will be displayed.
+
+Note that this method only supports two letter language codes. This
+means you cannot use `sv-se` format strings to distingish regional
+variants in the hostname. However, the first part of the language string
+does not need to be an official language code so you can use it to allow
+regional variants, e.g:
+
+ LANGUAGES:
+ - 'sv,Svenska,sv_SE'
+ - 'sf,Svenska,sv_FI'
+
+`http://sv.fixmystreet.com` would display `sv_SE` and
+`http://sf.fixmystreet.com` would display `sv_FI`. However, this would
+not be detected automatically (at the bare domain) if the user's browser was
+set to sv-fi.
+
+These language links can be used for adding a language switcher to the
+site. For example, a basic two language switcher:
+
+ [% IF lang_code == 'fr' %]
+ <li><a href="https://en.[% c.cobrand.base_host %][% c.req.uri.path_query %]">English</a></li>
+ [% ELSE %]
+ <li><a href="https://fr.[% c.cobrand.base_host %][% c.req.uri.path_query %]">Français</a></li>
+ [% END %]
+
+## Ensuring links in emails default to the right language
+
+With the default configuration links in emails will use the `BASE_URL`
+and hence clicking on them means the user will see the browser
+negotiated language. This behaviour can be changed using the
+`base_url_with_lang` function in your Cobrand module which is used
+when generating URLs for emails.
+
+A basic version of this that supports two languages would look like
+like this:
+
+ sub base_url_with_lang {
+ my $self = shift;
+ my $base = $self->base_url;
+ my $lang = $mySociety::Locale::lang;
+ if ($lang eq 'fr') {
+ $base =~ s{https?://}{$&fr.};
+ } else {
+ $base =~ s{https?://}{$&en.};
+ }
+ return $base;
+ }
+
+The current language is stored when a report is made and this is used
+when sending out emails related to the report. When the email is sent
+this means that `$mySociety::Locale::lang` returns the language used at
+the time the report was submitted, hence the function above will return
+URLs for the correct language.
+
+## Contributing a translation
+
+If we don't already have a translation for the language you want, please do
+consider contributing one :) You can use our repository on
+[Transifex](https://www.transifex.com/projects/p/fixmystreet/),
+or translate the `.po` files directly using a local program such as
+[PoEdit](http://www.poedit.net/).
+
+The templates use the `loc` function to pass strings to gettext for
+translation. If you create or update a `.po` file, you will need to run the
+`commonlib/bin/gettext-makemo` script to compile these files into the machine
+readable format used by the site.
+
+## Translating the FAQ and other static pages
+
+Static pages do not use gettext so need to be translated separately by
+creating a new template under your cobrand, e.g. for a German
+translation of the FAQ:
+
+ templates/web/<cobrand>/about/faq-de.html
+
+For other languages the file should be `faq-<lang>.html`. If there is
+not a translated template it will fall back to `faq.html`.
+
+## Translating body names, categories, and report states
+
+As long as you have set up the <code>LANGUAGES</code> configuration first, you
+will find that in the admin you can give translations for each of body names,
+report categories, and report states. These translations will be used as
+appropriate depending upon the language of the front end.
diff --git a/docs/customising/language/technical.md b/docs/customising/language/technical.md
new file mode 100644
index 000000000..11a10a147
--- /dev/null
+++ b/docs/customising/language/technical.md
@@ -0,0 +1,38 @@
+---
+layout: page
+title: Adding new strings to FixMyStreet
+---
+
+# Adding new strings
+
+<p class="lead">Technical details for people who wish to add new strings for
+translation.</p>
+
+You will need to install the Locale::Maketext::Extract package in order to
+parse strings out of templates:
+
+ $ cpanm -l local-carton Locale::Maketext::Extract
+
+A new clean `.po` file, containing all the strings marked for translation in
+the code and templates, can be created by running the `bin/gettext-extract`
+script.
+
+ export PERL5LIB="local-carton/lib/perl5:local/lib/perl5"
+ export PATH="local-carton/bin:$PATH"
+ bin/gettext-extract
+
+To merge in new strings with the existing translations:
+
+ bin/gettext-merge
+
+To compile translations into `.mo` files:
+
+ commonlib/bin/gettext-makemo
+
+You may find it helpful to add an alias to your .gitconfig:
+
+ [alias]
+ podiff = "!f() { git diff --color $@ | grep -v '^ ' | grep -v @@ | grep -v '#:' | less -FRSX; }; f"
+
+Then `git podiff locale` will show you actual changes, rather than all the
+changes to comments and line numbers.
diff --git a/docs/customising/login.md b/docs/customising/login.md
new file mode 100644
index 000000000..4b9cc25f1
--- /dev/null
+++ b/docs/customising/login.md
@@ -0,0 +1,41 @@
+---
+layout: page
+title: Login/authenticaton
+author: matthew
+---
+
+# Customising login/authentication
+
+<p class="lead">
+ This page describes the different possible forms of logging in.
+</p>
+
+By default, FixMyStreet uses email or password authentication. Confirmation
+emails are sent containing a link, clicking which confirms the account (and
+optionally sets a password for future use).
+
+## Social authentication
+
+If you set up a Facebook or a Twitter App, and provide its configuration
+details in your `general.yml`, then your users will be able to verify
+reports/updates and log in using their social media account. Using this method,
+FixMyStreet will still ask for and confirm an email address (if one is not
+provided by Facebook). The login form on the site automatically adjusts
+to allow people to pick whether to use the social login or the default email
+authentication.
+
+The Facebook App's domain should be set to your site's domain, and under
+advanced settings the OAuth redirect URL should be yourdomain/auth/Facebook.
+
+## Text authentication
+
+If you set up a <a href="https://www.twilio.com/">Twilio</a> account and enter
+the correct parameters in your configuration, you can also activate text
+authentication, whereby instead of a confirmation email being sent, a
+confirmation text is sent to the user's mobile containing a code they enter on
+the site to continue with their report/update/logging in. The user flow
+behaviour is otherwise identical, it is merely using a phone number instead of
+an email for authentication.
+
+On their profile page, users can add email/phone number, and verify ones they
+may have entered previously but not verified.
diff --git a/docs/customising/logo.md b/docs/customising/logo.md
new file mode 100644
index 000000000..f7d39b5a1
--- /dev/null
+++ b/docs/customising/logo.md
@@ -0,0 +1,29 @@
+---
+layout: page
+title: Customising the logo
+author: matthew
+---
+
+# Customising the logo
+
+<p class="lead">
+ This page describes how to change the logo of your installation.
+</p>
+
+Do make sure you have followed the
+[initial CSS guide]({{ "/customising/css/" | relative_url }}) first to set up the
+initial CSS for your own cobrand.
+
+To use a different logo, by default you should have an image 175x35 in size,
+preferably placed in `web/cobrands/YOURCOBRAND/` somewhere. You should then set
+the `background-image` property of `#site-logo` in your `base.scss`. If you
+wish a differently sized logo, you will also need to set the `width`, `height`,
+and `background-size` properties of `#site-logo`. Note if you make it larger in
+height, you might also need to investigate e.g. `$mappage-header-height`.
+
+On fixmystreet.com we use a larger logo on the desktop front page; if you wish
+to do the same, in your `layout.scss` set the `background-image` of
+`body.frontpage #site-logo`, along with (as before) corresponding `width`,
+`height`, and `background-size`. See fixmystreet.com’s `layout.scss` for how it
+does it, though note it is a bit more complex as it uses SVG with a PNG
+fallback.
diff --git a/docs/customising/send_reports.md b/docs/customising/send_reports.md
new file mode 100644
index 000000000..22d46034d
--- /dev/null
+++ b/docs/customising/send_reports.md
@@ -0,0 +1,83 @@
+---
+layout: page
+title: How FixMyStreet sends reports
+author: dave
+---
+
+# How FixMyStreet sends reports
+
+<p class="lead">
+After a user submits a problem, FixMyStreet sends a <strong>problem report</strong> to the body responsible for fixing it. Typically, reports
+are sent by email. It's possible to override the content of the report (the email template), or even the way in which it is sent.
+</p>
+
+## Check and send every few minutes
+
+FixMyStreet runs a task called `send-reports` at regular intervals (by default this is every 5 minutes) that finds all new reports and sends them on to the bodies responsible.
+
+To change the frequency of this job, change the `crontab` settings. Suggested values are in `conf/crontab.example`. You'll need to understand the Unix crontab syntax to make sense of that file. Be careful editing it if you are not familiar with crontab, because the syntax is very precise.
+
+## Which reports are sent?
+
+The `send-reports` task finds all *confirmed* reports that have not yet been sent, and runs through each one, determines which body (or bodies) it needs to go to, and sends them.
+
+Reports are usually confirmed by the user clicking on the confirmation link in the email that was sent to them.
+
+Alternatively, a report is marked as confirmed if it was created after the user logged in either with a password or by clicking on a confirmation link in an email (a browser session).
+
+It's possible to add a user who repeatedly sends abusive reports to the abuse list -- reports created by such users are automatically hidden and are never sent. To add a user to the abuse list, in the admin go to any report they have created and click on **Ban email address**.
+
+## Where does the report get sent?
+
+FixMyStreet uses the location of the problem to identify which bodies may be responsible for fixing it, and then decides which contact (typically an email address) to use) based on the chosen category. This is described in more detail on the page about [FMS and MapIt](/customising/fms_and_mapit).
+
+The actual contacts can be added, changed, or deleted via the admin. See [managing bodies and contacts](/running/bodies_and_contacts) for details.
+
+## What gets sent?
+
+If the contact is an email (which is the simplest and most common form of report sending) then the email template `templates/email/default/submit.txt` is used. This is a simple text-based email with a simple preamble and all the useful details from the report.
+
+If you want to change this (which is a good idea) add your own `submit.txt` to `templates/email/your-cobrand-name/`.
+
+## How to know if a report has been sent
+
+The public view of the report shows this: it says how long after creation the
+report was sent (for example, "Sent to South Borsetshire District Council two
+minutes later"). Alternatively, find the report in `admin/reports` -- the
+report will show a "when sent" date if the `send-reports` task has processed
+it successfully.
+
+## Alternatives to email
+
+Although by default FixMyStreet sends reports by email, it's possible to inject reports *directly* into some
+bodies' databases or back-end systems. This is usually much better than using email because it's more convenient
+for the staff working at the receiving end. See
+[more about integration]({{ "/customising/integration/" | relative_url }}) for details.
+
+## Technical investigation
+
+If you have access to your server and are comfortable using the command line,
+you can manually run the `send-reports` script. Normally you never need to do
+this because, as described above, FixMyStreet runs it using `crontab` every
+five minutes. But if you're investigating why reports aren't sending, you can
+run the script manually. The `send-reports` script normally runs silently, that
+is, it produces no output (this is to prevent cron sending a logging email
+every time it runs, including the times there are no reports to send anyway).
+But if you want to see what's going on, you can use these options:
+
+ * the `--verbose` option prints out a summary of reports that did not get
+ sent. Incidentally, this option is useful even in
+ <a href="{{ "/glossary/#production" | relative_url }}" class="glossary__link">production</a>,
+ because it causes cron to send a logging email containing this summary of
+ failed-to-send reports if anything goes wrong.
+
+ * the `--debug` option prints out detail about the sending process as
+ it is being attempted. As the script loops through each of the reports
+ it's trying to send, it will try to print out useful information for each
+ attempt. It also makes it clear if the script hasn't found *any* reports
+ to send.
+
+For example, to run `send-reports` with debugging output, do:
+
+ bin/send-reports --debug
+
diff --git a/docs/customising/static-pages.md b/docs/customising/static-pages.md
new file mode 100644
index 000000000..38ab02d60
--- /dev/null
+++ b/docs/customising/static-pages.md
@@ -0,0 +1,35 @@
+---
+layout: page
+title: Adding static pages
+---
+
+# Adding static pages
+
+<p class="lead">How to add your own static pages to your installation.</p>
+
+If you wish to add a new static page to your site, then you can place a
+template file, say `team.html`, in the `templates/web/cobrand/about/`
+directory, where `cobrand` should be replaced with your cobrand name (as
+explained in [customising FixMyStreet templates](../templates/)).
+
+The page will then be available to view at `/about/team` on your site.
+
+Have a look at the existing files in `templates/web/base/about/` for an idea
+of the contents of a file – you need a header and a footer include, but other
+than that the contents are up to you.
+
+If you want the page to be available in multiple languages, then name your file
+`team-LANG.html` for each language and it will automatically be used. For
+example, if your site is available in Welsh and French, you could have
+`team-cy.html` and `team-fr.html`
+
+<hr>
+
+As a special case, if you create an `about/homepage.html` template file, then
+it will be used as the front page of your site, and the normal front page will
+instead be available at `/report`.
+
+<hr>
+
+If you wish to do more complex pages, or wish to then we recommend setting up
+e.g. a WordPress installation running at a subdomain of your site.
diff --git a/docs/customising/templates.md b/docs/customising/templates.md
new file mode 100644
index 000000000..793156f70
--- /dev/null
+++ b/docs/customising/templates.md
@@ -0,0 +1,113 @@
+---
+layout: page
+title: Customising templates
+---
+
+# Customising FixMyStreet templates
+
+<p class="lead">This document explains how template inheritance works
+and how to create your own custom templates.</p>
+
+When it's building a page, FixMyStreet always looks in your cobrand's web
+template directory first: if it finds a template there, it uses it, and if it
+doesn't it falls back and uses the `base` one instead.
+
+ <svg width="300" height="160" xmlns="http://www.w3.org/2000/svg">
+ <g>
+ <g id="fms-template-stack">
+ <g id="fms_template_base">
+ <rect stroke="#000000" id="svg_8" height="50.185915" width="222.884508" y="100.373239" x="38.557748" stroke-width="3" fill="#ffffff"/>
+ <text stroke="#000000" transform="matrix(0.738028 0 0 0.738028 5.23944 6.41831)" xml:space="preserve" text-anchor="middle" font-family="Monospace" font-size="29" id="svg_13" y="170.305344" x="196.145042" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#000000">base</text>
+ </g>
+ <g id="fms-template-cobrand">
+ <path stroke="#000000" id="svg_18" d="m136.165344,36.887947l0,44.606102l-12.435638,0l28.656036,28.656036l28.656052,-28.926376l-14.598373,0.54068l0,-45.146778l-30.278076,0.270336z" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="3" fill="#ffffff"/>
+ <rect stroke="#000000" id="svg_11" height="50.185915" width="174.91267" y="15.5" x="62.543663" stroke-width="3" fill="#ffffff"/>
+ <text stroke="#000000" transform="matrix(0.738028 0 0 0.738028 5.23944 6.41831)" xml:space="preserve" text-anchor="middle" font-family="Monospace" font-size="29" id="svg_14" y="55.305344" x="196.145046" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#000000">your_cobrand</text>
+ <rect stroke="#000000" stroke-opacity="0" id="svg_19" height="5.660965" width="28.055539" y="62.210247" x="137.293877" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="3" fill="#ffffff"/>
+ </g>
+ </g>
+ </g>
+ </svg>
+
+To see how this works, look at some of the cobrands that already exist in the
+`templates/web` directory. You need to create a new directory with your
+cobrand's name: for example, do:
+
+ mkdir templates/web/fixmypark
+
+Then, to override an existing template, copy it into the
+`templates/web/fixmypark/` directory and edit it there. You *must* use the
+same directory and file names as in the parent cobrand (that is, in
+`templates/web/base`).
+
+<div class="attention-box">
+ <strong>Please note:</strong> only make template files for those things you
+ need to do differently; you do not need to copy all the files into your own
+ templates folder. If the change you want to make is very small to the
+ base template, you could consider just adding an <code>IF</code>
+ statement to that parent template instead. The
+ <a href="/feeding-back/">Feeding back page</a> has more details.
+</div>
+
+One template you will probably want to override is the `site-name.html`, which
+contains the name of your site for use in various other templates, and e.g. the
+site's &lt;title&gt;. Copy this template into your cobrand like this:
+
+ cp templates/web/base/site-name.html templates/web/fixmypark/
+
+Or it’s likely you’ll want to change the footer template, which puts text right
+at the bottom of every page. Copy the footer template into your cobrand like
+this:
+
+ cp templates/web/base/footer.html templates/web/fixmypark/
+
+The templates use the popular <a
+href="http://www.template-toolkit.org">Template Toolkit</a> system &mdash; look
+inside and you'll see HTML with placeholders like `[% THIS %]`. The `[% INCLUDE
+...%]` marker pulls in another template, which, just like the footer, you can
+copy into your own cobrand from `fixmystreet` or `base` and edit.
+
+<div class="attention-box warning">
+ One thing to be careful of: <strong>only edit the <code>.html</code> files</strong>. FixMyStreet
+ generates <code>.ttc</code> versions, which are cached copies &mdash; don't edit these, they
+ automatically get created (and overwritten) when FixMyStreet is running.
+</div>
+
+The other template you will probably make your own version of is the FAQ which
+is in `templates/web/base/about/faq-en-gb.html`. If you translate it too,
+you will need to rename it accordingly.
+
+## Emails
+
+There are also email templates that FixMyStreet uses when it constructs email
+messages to send out. You can override these in a similar way: look in the
+`templates/email` directory and you'll see cobrands overriding the templates in
+`templates/email/default`.
+
+For example, many of the email templates themselves use the small
+`site-name.txt` and `signature.txt` templates, so you may want to override
+these (by copying them from `templates/email/default` into your own cobrand's
+directory within `templates/email`, and editing them) even if you're not
+changing anything else. On the other hand, you may wish to create new versions
+of all the emails in order to translate them.
+
+<div class="attention-box helpful-hint">
+Please do not translate the `Subject:` at the beginning of the first line, as
+that is used by the code to locate the Subject line of the email.
+</div>
+
+You may also send out HTML emails, by creating templates with an `.html`
+extension as well as the plain text `.txt` one. In order to save you a lot of
+time making working HTML emails, you may want to override the
+`_email_color_overrides.html` and `_email_setting_overrides.html` templates to
+set your own colours/branding, and then only copy other HTML templates to
+translate or otherwise change the wording.
+
+To preview HTML emails, when running the development server go to `/_dev/email/`
+and click the email you wish to preview.
+
+To include an inline logo in your HTML email, put it at
+`web/cobrands/yourcobrands/images/email-logo.gif` and make sure `logo_width`
+and `logo_height` are set appropriately in your
+`_email_setting_overrides.html`. The email template should then pick it up
+automatically.