diff --git a/doc/_themes/odoodoc/layout.html b/doc/_themes/odoodoc/layout.html
index 7685d8af25fcdf2b4131b79a6d1de889fb2e0c07..1a68d31814a093e700dab860812bef21d824c84d 100644
--- a/doc/_themes/odoodoc/layout.html
+++ b/doc/_themes/odoodoc/layout.html
@@ -32,7 +32,7 @@
   <div class="sphinxsidebar">
     <div class="sphinxsidebarwrapper">
       {{ toctree(maxdepth=4, collapse=False, includehidden=True,
-                 main_navbar=False, titles_only=False) }}
+                 navbar='side', titles_only=False) }}
       {% if github_link %}
         <p><a href="{{ github_link(mode='edit') }}" class="github">
           Edit on GitHub
@@ -72,7 +72,8 @@
       {% endif %}
     </div>
     <nav class="collapse navbar-collapse navbar-main" role="navigation">
-      {{ toctree(titles_only=True, maxdepth=2, includehidden=True, collapse=False) }}
+      {{ toctree(titles_only=True, maxdepth=2, includehidden=True,
+                 collapse=False, navbar='main') }}
     </nav>
   </div>
 </header>
diff --git a/doc/_themes/odoodoc/sphinx_monkeypatch.py b/doc/_themes/odoodoc/sphinx_monkeypatch.py
index 13c3a305988bb543c64f835493a9d4705d7ad71b..182fef89c8d0a3fb6a8171b766947389ba61c826 100644
--- a/doc/_themes/odoodoc/sphinx_monkeypatch.py
+++ b/doc/_themes/odoodoc/sphinx_monkeypatch.py
@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
 import sphinx.roles
 import sphinx.environment
-from sphinx.builders.html import StandaloneHTMLBuilder
 from sphinx.writers.html import HTMLTranslator
 from docutils.writers.html4css1 import HTMLTranslator as DocutilsTranslator
 
@@ -9,27 +8,17 @@ def patch():
     # navify toctree (oh god)
     @monkey(sphinx.environment.BuildEnvironment)
     def resolve_toctree(old_resolve, self, *args, **kwargs):
-        """ If main_navbar, bootstrapify TOC to yield a navbar
+        """ If navbar, bootstrapify TOC to yield a navbar
 
         """
-        main_navbar = kwargs.pop('main_navbar', False)
+        navbar = kwargs.pop('navbar', None)
         toc = old_resolve(self, *args, **kwargs)
         if toc is None:
             return None
 
-        navbarify(toc[0], main_navbar=main_navbar)
+        navbarify(toc[0], navbar=navbar)
         return toc
 
-    @monkey(StandaloneHTMLBuilder)
-    def _get_local_toctree(old_local, self, *args, **kwargs):
-        """ _get_local_toctree generates a documentation toctree for the local
-        document (?), called from handle_page
-        """
-        # so can call toctree(main_navbar=False)
-        d = {'main_navbar': True}
-        d.update(kwargs)
-        return old_local(self, *args, **d)
-
     # monkeypatch visit_table to remove border and add .table
     HTMLTranslator.visit_table = visit_table
     # disable colspec crap
@@ -37,11 +26,18 @@ def patch():
     # copy data- attributes straight from source to dest
     HTMLTranslator.starttag = starttag_data
 
-def navbarify(node, main_navbar=False):
-    # add classes to toplevel
-    if not main_navbar:
-        navify([node])
-    else:
+def navbarify(node, navbar=None):
+    """
+    :param node: toctree node to navbarify
+    :param navbar: Whether this toctree is a 'main' navbar, a 'side' navbar or
+                   not a navbar at all
+    """
+    if navbar == 'side':
+        for n in node.traverse():
+            if n.tagname == 'bullet_list':
+                n['classes'].append('nav')
+    elif navbar == 'main':
+        # add classes to just toplevel
         node['classes'].extend(['nav', 'navbar-nav', 'navbar-right'])
         for list_item in node.children:
             # bullet_list
@@ -52,6 +48,10 @@ def navbarify(node, main_navbar=False):
             #             list_item
             #                 compact_paragraph
             #                     reference
+            # no bullet_list.list_item -> don't dropdownify
+            if not list_item.children[1].children:
+                return
+
             list_item['classes'].append('dropdown')
             # list_item.compact_paragraph.reference
             link = list_item.children[0].children[0]
@@ -59,11 +59,6 @@ def navbarify(node, main_navbar=False):
             link.attributes['data-toggle'] = 'dropdown'
             # list_item.bullet_list
             list_item.children[1]['classes'].append('dropdown-menu')
-def navify(nodes):
-    for node in nodes:
-        if node.tagname == 'bullet_list':
-            node['classes'].append('nav')
-        navify(node.children)
 
 def visit_table(self, node):
     """
diff --git a/doc/_themes/odoodoc/static/style.css b/doc/_themes/odoodoc/static/style.css
index 19f5270109e0770e11d0b286d3495f5af7075bd1..7c0b8e82959cf4f269ce6e29bbc490f9ff71afe2 100644
--- a/doc/_themes/odoodoc/static/style.css
+++ b/doc/_themes/odoodoc/static/style.css
@@ -5902,8 +5902,10 @@ button.close {
 .panel-body:after,
 .modal-footer:before,
 .modal-footer:after,
-.document-super:before,
-.document-super:after,
+.document-super:not(.stripe):before,
+.document-super:not(.stripe):after,
+.document-super.stripe:before,
+.document-super.stripe:after,
 .document:before,
 .document:after {
   content: " ";
@@ -5924,7 +5926,8 @@ button.close {
 .pager:after,
 .panel-body:after,
 .modal-footer:after,
-.document-super:after,
+.document-super:not(.stripe):after,
+.document-super.stripe:after,
 .document:after {
   clear: both;
 }
@@ -6181,35 +6184,53 @@ body {
   overflow: auto;
   position: relative;
 }
-.document-super {
+.document-super:not(.stripe) {
   margin-right: auto;
   margin-left: auto;
   padding-left: 15px;
   padding-right: 15px;
 }
 @media (min-width: 768px) {
-  .document-super {
+  .document-super:not(.stripe) {
     width: 750px;
   }
 }
 @media (min-width: 992px) {
-  .document-super {
+  .document-super:not(.stripe) {
     width: 970px;
   }
 }
 @media (min-width: 1200px) {
-  .document-super {
+  .document-super:not(.stripe) {
     width: 1170px;
   }
 }
-.document-super > .navbar-header,
-.document-super > .navbar-collapse {
+.document-super:not(.stripe) > .navbar-header,
+.document-super:not(.stripe) > .navbar-collapse {
   margin-right: -15px;
   margin-left: -15px;
 }
 @media (min-width: 768px) {
-  .document-super > .navbar-header,
-  .document-super > .navbar-collapse {
+  .document-super:not(.stripe) > .navbar-header,
+  .document-super:not(.stripe) > .navbar-collapse {
+    margin-right: 0;
+    margin-left: 0;
+  }
+}
+.document-super.stripe {
+  margin-right: auto;
+  margin-left: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+.document-super.stripe > .navbar-header,
+.document-super.stripe > .navbar-collapse {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .document-super.stripe > .navbar-header,
+  .document-super.stripe > .navbar-collapse {
     margin-right: 0;
     margin-left: 0;
   }
@@ -6296,7 +6317,7 @@ body {
   -o-transition: all 0.3s ease-out;
   transition: all 0.3s ease-out;
 }
-.docs-nav .navbar-nav > li > a:after {
+.docs-nav .navbar-nav > li.dropdown > a:after {
   content: " ";
   display: inline-block;
   width: 0;
@@ -6307,7 +6328,7 @@ body {
   border-right: 4px solid transparent;
   border-left: 4px solid transparent;
 }
-.docs-nav .navbar-nav > li .dropdown-menu > li.current > a.current {
+.docs-nav .navbar-nav > li.dropdown .dropdown-menu > li.current > a.current {
   background-color: #a24689;
   color: white;
 }
@@ -6709,6 +6730,74 @@ td.field-body > ul {
 .descclassname {
   opacity: 0.5;
 }
+.index-tree ul,
+.index-tree li {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+}
+.index-tree > ul > li {
+  margin-bottom: 0.5em;
+}
+.index-tree > ul > li > a {
+  font-family: Lato, Arial, sans-serif;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+  margin-top: 20px;
+  margin-bottom: 10px;
+  font-size: 24px;
+  text-align: center;
+}
+.index-tree > ul > li > a small,
+.index-tree > ul > li > a .small {
+  font-weight: normal;
+  line-height: 1;
+  color: #777777;
+}
+.index-tree > ul > li > a small,
+.index-tree > ul > li > a .small {
+  font-size: 65%;
+}
+.index-tree > ul > li > ul {
+  display: -webkit-flex;
+  display: flex;
+  -webkit-flex-wrap: wrap;
+  flex-wrap: wrap;
+}
+.index-tree > ul > li > ul > li {
+  width: 50%;
+}
+.index-tree > ul > li > ul > li a {
+  font-family: Lato, Arial, sans-serif;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+  margin-top: 10px;
+  margin-bottom: 10px;
+  font-size: 18px;
+  padding-left: 10%;
+  padding-right: 10%;
+}
+.index-tree > ul > li > ul > li a small,
+.index-tree > ul > li > ul > li a .small {
+  font-weight: normal;
+  line-height: 1;
+  color: #777777;
+}
+.index-tree > ul > li > ul > li a small,
+.index-tree > ul > li > ul > li a .small {
+  font-size: 75%;
+}
+.index-tree > ul > li a {
+  display: block;
+  color: #a24689 !important;
+  padding: 0.3em 0;
+  margin: 3px !important;
+}
+.index-tree > ul > li a:hover {
+  background-color: #eeeeee;
+}
 .stripe .section {
   margin-bottom: 2em;
 }
diff --git a/doc/_themes/odoodoc/static/style.less b/doc/_themes/odoodoc/static/style.less
index 719fa6f10e3fe3ddf4beef0dfd84a1d2eb3aa5ed..ea53cd95e8526c2ae0736fe69d333228510296d4 100644
--- a/doc/_themes/odoodoc/static/style.less
+++ b/doc/_themes/odoodoc/static/style.less
@@ -25,9 +25,12 @@ body {
   position: relative;
 }
 
-.document-super {
+.document-super:not(.stripe) {
   .container();
 }
+.document-super.stripe {
+  .container-fluid();
+}
 
 .document {
   .make-row();
@@ -89,20 +92,22 @@ body {
       opacity: 0;
       .transition(all 0.3s ease-out);
     }
-    > a:after {
-      content: " ";
-      display: inline-block;
-      width: 0;
-      height: 0;
-      margin-left: 5px;
-      vertical-align: middle;
-      border-top: 4px solid @gray-light;
-      border-right: 4px solid transparent;
-      border-left: 4px solid transparent;
-    }
-    .dropdown-menu > li.current > a.current {
-      background-color: @brand-primary;
-      color: white;
+    &.dropdown {
+      > a:after {
+        content: " ";
+        display: inline-block;
+        width: 0;
+        height: 0;
+        margin-left: 5px;
+        vertical-align: middle;
+        border-top: 4px solid @gray-light;
+        border-right: 4px solid transparent;
+        border-left: 4px solid transparent;
+      }
+      .dropdown-menu > li.current > a.current {
+        background-color: @brand-primary;
+        color: white;
+      }
     }
   }
   /* version switcher */
@@ -547,6 +552,44 @@ td.field-body {
   opacity: 0.5;
 }
 
+
+.index-tree {
+  ul, li {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+  }
+  > ul > li {
+    margin-bottom: 0.5em;
+    > a {
+      .h3();
+      text-align: center;
+    }
+    > ul {
+      display: -webkit-flex;
+      display: flex;
+      -webkit-flex-wrap: wrap;
+      flex-wrap: wrap;
+      > li {
+        width: 50%;
+        a {
+          .h4();
+          padding-left: 10%;
+          padding-right: 10%;
+        }
+      }
+    }
+    a {
+      display: block;
+      color: @link-color !important;
+      padding: 0.3em 0;
+      margin: 3px !important;
+      &:hover {
+        background-color: @gray-lighter;
+      }
+    }
+  }
+}
 // STRIPE-STYLE PAGES
 .stripe {
   .section {
diff --git a/doc/modules/api_integration.rst b/doc/api_integration.rst
similarity index 99%
rename from doc/modules/api_integration.rst
rename to doc/api_integration.rst
index 21d0163ba4691a8a57465f0f87ce87fd6050f2a0..12c5b56737e8dff83369709e1c6d68a302273433 100644
--- a/doc/modules/api_integration.rst
+++ b/doc/api_integration.rst
@@ -1,7 +1,7 @@
 :classes: stripe
 
 ===========
-Odoo as API
+Web Service
 ===========
 
 Odoo is mostly extended internally via modules, but much of its features and
@@ -250,8 +250,8 @@ the login.
 Calling methods
 ===============
 
-The second — and most generally useful — is ``xmlrpc/2/object`` which is used
-to call methods of odoo models via the ``execute_kw`` RPC function.
+The second endpoint is ``xmlrpc/2/object``, is used to call methods of odoo
+models via the ``execute_kw`` RPC function.
 
 Each call to ``execute_kw`` takes the following parameters:
 
diff --git a/doc/images/view-on-github.png b/doc/images/view-on-github.png
deleted file mode 100644
index 65a8d42363de1b3414c175ca606491f74ca30b8d..0000000000000000000000000000000000000000
Binary files a/doc/images/view-on-github.png and /dev/null differ
diff --git a/doc/index.rst b/doc/index.rst
index 3c1696020d6a4cc65769484d319c45c722012653..56f58b6aa0d428aecdbef384698889251920a2df 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -4,38 +4,17 @@ odoo developer documentation
 
 Welcome to the Odoo developer documentation.
 
-This documentation is incomplete and may contain errors, if you wish to
-contribute, every page should have a :guilabel:`View on Github` link:
-
-.. image:: images/view-on-github.*
-    :align: center
-
-Through this link you can edit documents and submit changes for review using
-`github's web interface
-<https://help.github.com/articles/editing-files-in-your-repository/>`_.
-Contributions are welcome and appreciated.
-
 .. todo:: what's the documentation's license?
 
-The documentation is currently organized in four sections:
-
-* :doc:`tutorials`, aimed at introducing the primary areas of developing Odoo
-  modules
-* :doc:`reference`, which ought be the complete and canonical documentation
-  for Odoo subsystems
-* :doc:`modules`, documenting useful specialized modules and integration
-  methods (and currently empty)
-
-.. hidden toctree w/o titlesonly otherwise the titlesonly "sticks" to
-   in-document toctrees and we can't have a toctree showing both "sibling"
-   pages and current document sections
-
+.. rst-class:: index-tree
+.. titlesonly breaks level 3 (~in-document) toc of left navbar, so use
+   maxdepth instead
 .. toctree::
-    :hidden:
+    :maxdepth: 2
 
     tutorials
     reference
-    modules
+    api_integration
 
 .. ifconfig:: todo_include_todos
 
diff --git a/doc/modules.rst b/doc/modules.rst
deleted file mode 100644
index cb5ed8d6ca1590e0a11610235006fb7124c5ac36..0000000000000000000000000000000000000000
--- a/doc/modules.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-==============
-Module Objects
-==============
-
-.. toctree::
-    :titlesonly:
-
-    modules/api_integration
diff --git a/doc/reference/cmdline.rst b/doc/reference/cmdline.rst
index 32c1ef487295c2e74a39668d0f535b6a39b79e0a..1ec7d96ae9d8013eef326dcd18d49276d4b60761 100644
--- a/doc/reference/cmdline.rst
+++ b/doc/reference/cmdline.rst
@@ -71,7 +71,7 @@ Scaffolding is available via the :command:`odoo.py scaffold` subcommand.
 .. option:: -t <template>
 
     a template directory, files are passed through jinja2_ then copied to
-    the :option:`destination` directory
+    the ``destination`` directory
 
 .. option:: name
 
diff --git a/doc/reference/orm.rst b/doc/reference/orm.rst
index 94aa18b48638b8212a65ff28c66e68a2932649dc..cfc465078b197afcc5e8b43844d24ac6914b19cc 100644
--- a/doc/reference/orm.rst
+++ b/doc/reference/orm.rst
@@ -421,10 +421,31 @@ added.
     is not written to the database, just used to know which value to send back
     to the client
 
+Low-level SQL
+-------------
+
+The :attr:`~openerp.api.Environment.cr` attribute on environments is the
+cursor for the current database transaction and allows executing SQL directly,
+either for queries which are difficult to express using the ORM (e.g. complex
+joins) or for performance reasons::
+
+    self.env.cr.execute("some_sql", param1, param2, param3)
+
+Because models use the same cursor and the :class:`~openerp.api.Environment`
+holds various caches, these caches must be invalidated when *altering* the
+database in raw SQL, or further uses of models may become incoherent. It is
+necessary to clear caches when using ``CREATE``, ``UPDATE`` or ``DELETE`` in
+SQL, but not ``SELECT`` (which simply reads the database).
+
+Clearing caches can be performed using the
+:meth:`~openerp.api.Environment.invalidate_all` method of the
+:class:`~openerp.api.Environment` object.
+
+
 .. _reference/orm/oldapi:
 
 Old API compatibility
----------------------
+=====================
 
 Odoo is currently transitioning from an older (less regular) API, it can be
 necessary to manually bridge from one to the other manually:
@@ -508,170 +529,6 @@ return lists of ids, there is also a decorator managing this:
         >>> old_style_model.some_method(cr, uid, [1, 2, 3], context=context)
         [1, 2, 3]
 
-Porting from the old API
-------------------------
-
-* methods still written in the old API should be automatically bridged by the
-  ORM, no need to switch to the old API, just call them as if they were a new
-  API method. See :ref:`reference/orm/oldapi/bridging` for more details.
-* ``search`` returns a recordset, no point in e.g. browsing its result
-* ``fields.related`` and ``fields.function`` are replaced by using a normal
-  field type with either a ``related`` or a ``compute`` parameter
-* ``depends`` on field compute methods **must be complete**, it must list
-  **all** the fields and sub-fields which the compute method uses. It is
-  better to have too many dependencies (will recompute the field in cases
-  where that is not needed) than not enough (will forget to recompute the
-  field and then values will be incorrect)
-* **remove** all ``onchange`` methods on computed fields. Computed fields are
-  automatically re-computed when one of their dependencies is changed, and
-  that is used to auto-generate ``onchange`` by the client
-* the decorators :func:`~openerp.api.model` and :func:`~openerp.api.multi` are
-  for bridging *when calling from the old API context*, for internal or pure
-  new-api (e.g. compute) they are useless
-* remove :attr:`~openerp.models.Model._default`, replace by ``default=``
-  parameter on corresponding fields
-* if a field's ``string`` is the titlecased version of the field name::
-
-    name = fields.Char(string="Name")
-
-  it is useless and should be removed
-* ``multi`` does not do anything on new API fields use the same ``compute``
-  methods on all relevant fields for the same result
-* provide ``compute``, ``inverse`` and ``search`` methods by name (as a
-  string), this makes them overridable (removes the need for an intermediate
-  "trampoline" function)
-* double check that all fields and methods have different names, there is no
-  warning in case of collision (because Python handles it before Odoo sees
-  anything)
-* the normal new-api import is ``from openerp import fields, models``. If
-  compatibility decorators are necessary, use ``from openerp import api,
-  fields, models``
-* avoid the :func:`~openerp.api.one` decorator, it probably does not do what
-  you expect
-* remove explicit definition of :attr:`~openerp.models.Model.create_uid`,
-  :attr:`~openerp.models.Model.create_date`,
-  :attr:`~openerp.models.Model.write_uid` and
-  :attr:`~openerp.models.Model.write_date` fields: they are now created as
-  regular "legitimate" fields, and can be read and written like any other
-  field out-of-the-box
-* when straight conversion is impossible (semantics can not be bridged) or the
-  "old API" version is not desirable and could be improved for the new API, it
-  is possible to use completely different "old API" and "new API"
-  implementations for the same method name using :func:`~openerp.api.v7` and
-  :func:`~openerp.api.v8`. The method should first be defined using the
-  old-API style and decorated with :func:`~openerp.api.v7`, it should then be
-  re-defined using the exact same name but the new-API style and decorated
-  with :func:`~openerp.api.v8`. Calls from an old-API context will be
-  dispatched to the first implementation and calls from a new-API context will
-  be dispatched to the second implementation. One implementation can call (and
-  frequently does) call the other by switching context.
-
-  .. danger:: using these decorators makes methods extremely difficult to
-              override and harder to understand and document
-* uses of :attr:`~openerp.models.Model._columns` or
-  :attr:`~openerp.models.Model._all_columns` should be replaced by
-  :attr:`~openerp.models.Model._fields`, which provides access to instances of
-  new-style :class:`openerp.fields.Field` instances (rather than old-style
-  :class:`openerp.osv.fields._column`).
-
-  Non-stored computed fields created using the new API style are *not*
-  available in :attr:`~openerp.models.Model._columns` and can only be
-  inspected through :attr:`~openerp.models.Model._fields`
-* reassigning ``self`` in a method is probably unnecessary and may break
-  translation introspection
-* :class:`~openerp.api.Environment` objects rely on some threadlocal state,
-  which has to be set up before using them. It is necessary to do so using the
-  :meth:`openerp.api.Environment.manage` context manager when trying to use
-  the new API in contexts where it hasn't been set up yet, such as new threads
-  or a Python interactive environment::
-
-    >>> from openerp import api, modules
-    >>> r = modules.registry.RegistryManager.get('test')
-    >>> cr = r.cursor()
-    >>> env = api.Environment(cr, 1, {})
-    Traceback (most recent call last):
-      ...
-    AttributeError: environments
-    >>> with api.Environment.manage():
-    ...     env = api.Environment(cr, 1, {})
-    ...     print env['res.partner'].browse(1)
-    ...
-    res.partner(1,)
-
-.. _reference/orm/oldapi/bridging:
-
-Automatic bridging of old API methods
-'''''''''''''''''''''''''''''''''''''
-
-When models are initialized, all methods are automatically scanned and bridged
-if they look like models declared in the old API style. This bridging makes
-them transparently callable from new-API-style methods.
-
-Methods are matched as "old-API style" if their second positional parameter
-(after ``self``) is called either ``cr`` or ``cursor``. The system also
-recognizes the third positional parameter being called ``uid`` or ``user`` and
-the fourth being called ``id`` or ``ids``. It also recognizes the presence of
-any parameter called ``context``.
-
-When calling such methods from a new API context, the system will
-automatically fill matched parameters from the current
-:class:`~openerp.api.Environment` (for :attr:`~openerp.api.Environment.cr`,
-:attr:`~openerp.api.Environment.user` and
-:attr:`~openerp.api.Environment.context`) or the current recordset (for ``id``
-and ``ids``).
-
-In the rare cases where it is necessary, the bridging can be customized by
-decorating the old-style method:
-
-* disabling it entirely, by decorating a method with
-  :func:`~openerp.api.noguess` there will be no bridging and methods will be
-  called the exact same way from the new and old API styles
-* defining the bridge explicitly, this is mostly for methods which are matched
-  incorrectly (because parameters are named in unexpected ways):
-
-  :func:`~openerp.api.cr`
-     will automatically prepend the current cursor to explicitly provided
-     parameters, positionally
-  :func:`~openerp.api.cr_uid`
-     will automatically prepend the current cursor and user's id to explictly
-     provided parameters
-  :func:`~openerp.api.cr_uid_ids`
-     will automatically prepend the current cursor, user's id and recordset's
-     ids to explicitly provided parameters
-  :func:`~openerp.api.cr_uid_id`
-     will loop over the current recordset and call the method once for each
-     record, prepending the current cursor, user's id and record's id to
-     explicitly provided parameters.
-
-     .. danger:: the result of this wrapper is *always a list* when calling
-                 from a new-API context
-
-  All of these methods have a ``_context``-suffixed version
-  (e.g. :func:`~openerp.api.cr_uid_context`) which also passes the current
-  context *by keyword*.
-* dual implementations using :func:`~openerp.api.v7` and
-  :func:`~openerp.api.v8` will be ignored as they provide their own "bridging"
-
-Low-level SQL
--------------
-
-The :attr:`~openerp.api.Environment.cr` attribute on environments is the
-cursor for the current database transaction and allows executing SQL directly,
-either for queries which are difficult to express using the ORM (e.g. complex
-joins) or for performance reasons::
-
-    self.env.cr.execute("some_sql", param1, param2, param3)
-
-Because models use the same cursor and the :class:`~openerp.api.Environment`
-holds various caches, these caches must be invalidated when *altering* the
-database in raw SQL, or further uses of models may become incoherent. It is
-necessary to clear caches when using ``CREATE``, ``UPDATE`` or ``DELETE`` in
-SQL, but not ``SELECT`` (which simply reads the database).
-
-Clearing caches can be performed using the
-:meth:`~openerp.api.Environment.invalidate_all` method of the
-:class:`~openerp.api.Environment` object.
-
 .. _reference/orm/model:
 
 Model Reference
@@ -1168,3 +1025,148 @@ Domain criteria can be combined using logical operators in *prefix* form:
             (name is 'ABC')
         AND (language is NOT english)
         AND (country is Belgium OR Germany)
+
+Porting from the old API
+========================
+
+* methods still written in the old API should be automatically bridged by the
+  ORM, no need to switch to the old API, just call them as if they were a new
+  API method. See :ref:`reference/orm/oldapi/bridging` for more details.
+* :meth:`~openerp.models.Model.search` returns a recordset, no point in e.g.
+  browsing its result
+* ``fields.related`` and ``fields.function`` are replaced by using a normal
+  field type with either a ``related=`` or a ``compute=`` parameter
+* :func:`~openerp.api.depends` on ``compute=`` methods **must be complete**,
+  it must list **all** the fields and sub-fields which the compute method
+  uses. It is better to have too many dependencies (will recompute the field
+  in cases where that is not needed) than not enough (will forget to recompute
+  the field and then values will be incorrect)
+* **remove** all ``onchange`` methods on computed fields. Computed fields are
+  automatically re-computed when one of their dependencies is changed, and
+  that is used to auto-generate ``onchange`` by the client
+* the decorators :func:`~openerp.api.model` and :func:`~openerp.api.multi` are
+  for bridging *when calling from the old API context*, for internal or pure
+  new-api (e.g. compute) they are useless
+* remove :attr:`~openerp.models.Model._default`, replace by ``default=``
+  parameter on corresponding fields
+* if a field's ``string=`` is the titlecased version of the field name::
+
+    name = fields.Char(string="Name")
+
+  it is useless and should be removed
+* the ``multi=`` parameter does not do anything on new API fields use the same
+  ``compute=`` methods on all relevant fields for the same result
+* provide ``compute=``, ``inverse=`` and ``search=`` methods by name (as a
+  string), this makes them overridable (removes the need for an intermediate
+  "trampoline" function)
+* double check that all fields and methods have different names, there is no
+  warning in case of collision (because Python handles it before Odoo sees
+  anything)
+* the normal new-api import is ``from openerp import fields, models``. If
+  compatibility decorators are necessary, use ``from openerp import api,
+  fields, models``
+* avoid the :func:`~openerp.api.one` decorator, it probably does not do what
+  you expect
+* remove explicit definition of :attr:`~openerp.models.Model.create_uid`,
+  :attr:`~openerp.models.Model.create_date`,
+  :attr:`~openerp.models.Model.write_uid` and
+  :attr:`~openerp.models.Model.write_date` fields: they are now created as
+  regular "legitimate" fields, and can be read and written like any other
+  field out-of-the-box
+* when straight conversion is impossible (semantics can not be bridged) or the
+  "old API" version is not desirable and could be improved for the new API, it
+  is possible to use completely different "old API" and "new API"
+  implementations for the same method name using :func:`~openerp.api.v7` and
+  :func:`~openerp.api.v8`. The method should first be defined using the
+  old-API style and decorated with :func:`~openerp.api.v7`, it should then be
+  re-defined using the exact same name but the new-API style and decorated
+  with :func:`~openerp.api.v8`. Calls from an old-API context will be
+  dispatched to the first implementation and calls from a new-API context will
+  be dispatched to the second implementation. One implementation can call (and
+  frequently does) call the other by switching context.
+
+  .. danger:: using these decorators makes methods extremely difficult to
+              override and harder to understand and document
+* uses of :attr:`~openerp.models.Model._columns` or
+  :attr:`~openerp.models.Model._all_columns` should be replaced by
+  :attr:`~openerp.models.Model._fields`, which provides access to instances of
+  new-style :class:`openerp.fields.Field` instances (rather than old-style
+  :class:`openerp.osv.fields._column`).
+
+  Non-stored computed fields created using the new API style are *not*
+  available in :attr:`~openerp.models.Model._columns` and can only be
+  inspected through :attr:`~openerp.models.Model._fields`
+* reassigning ``self`` in a method is probably unnecessary and may break
+  translation introspection
+* :class:`~openerp.api.Environment` objects rely on some threadlocal state,
+  which has to be set up before using them. It is necessary to do so using the
+  :meth:`openerp.api.Environment.manage` context manager when trying to use
+  the new API in contexts where it hasn't been set up yet, such as new threads
+  or a Python interactive environment::
+
+    >>> from openerp import api, modules
+    >>> r = modules.registry.RegistryManager.get('test')
+    >>> cr = r.cursor()
+    >>> env = api.Environment(cr, 1, {})
+    Traceback (most recent call last):
+      ...
+    AttributeError: environments
+    >>> with api.Environment.manage():
+    ...     env = api.Environment(cr, 1, {})
+    ...     print env['res.partner'].browse(1)
+    ...
+    res.partner(1,)
+
+.. _reference/orm/oldapi/bridging:
+
+Automatic bridging of old API methods
+-------------------------------------
+
+When models are initialized, all methods are automatically scanned and bridged
+if they look like models declared in the old API style. This bridging makes
+them transparently callable from new-API-style methods.
+
+Methods are matched as "old-API style" if their second positional parameter
+(after ``self``) is called either ``cr`` or ``cursor``. The system also
+recognizes the third positional parameter being called ``uid`` or ``user`` and
+the fourth being called ``id`` or ``ids``. It also recognizes the presence of
+any parameter called ``context``.
+
+When calling such methods from a new API context, the system will
+automatically fill matched parameters from the current
+:class:`~openerp.api.Environment` (for :attr:`~openerp.api.Environment.cr`,
+:attr:`~openerp.api.Environment.user` and
+:attr:`~openerp.api.Environment.context`) or the current recordset (for ``id``
+and ``ids``).
+
+In the rare cases where it is necessary, the bridging can be customized by
+decorating the old-style method:
+
+* disabling it entirely, by decorating a method with
+  :func:`~openerp.api.noguess` there will be no bridging and methods will be
+  called the exact same way from the new and old API styles
+* defining the bridge explicitly, this is mostly for methods which are matched
+  incorrectly (because parameters are named in unexpected ways):
+
+  :func:`~openerp.api.cr`
+     will automatically prepend the current cursor to explicitly provided
+     parameters, positionally
+  :func:`~openerp.api.cr_uid`
+     will automatically prepend the current cursor and user's id to explictly
+     provided parameters
+  :func:`~openerp.api.cr_uid_ids`
+     will automatically prepend the current cursor, user's id and recordset's
+     ids to explicitly provided parameters
+  :func:`~openerp.api.cr_uid_id`
+     will loop over the current recordset and call the method once for each
+     record, prepending the current cursor, user's id and record's id to
+     explicitly provided parameters.
+
+     .. danger:: the result of this wrapper is *always a list* when calling
+                 from a new-API context
+
+  All of these methods have a ``_context``-suffixed version
+  (e.g. :func:`~openerp.api.cr_uid_context`) which also passes the current
+  context *by keyword*.
+* dual implementations using :func:`~openerp.api.v7` and
+  :func:`~openerp.api.v8` will be ignored as they provide their own "bridging"