diff --git a/doc/api/api.pro b/doc/api/api.pro
index cfa103dee7c204eb6970dbcad12735fc6a78a6e3..6cce0829112210b8b2f142623e62652fa71c595f 100644
--- a/doc/api/api.pro
+++ b/doc/api/api.pro
@@ -45,6 +45,7 @@ HELP_DEP_FILES = $$PWD/qtcreator-api.qdoc \
                  $$PWD/coding-style.qdoc \
                  $$PWD/external-tool-spec.qdoc \
                  $$PWD/qtcreator-dev.qdoc \
+                 $$PWD/qtcreator-dev-wizards.qdoc \
                  $$PWD/qtcreator-dev.qdocconf
 
 docs.name = CREATE API DOC
diff --git a/doc/api/examples/webpagewizard/webpagewizard.cpp b/doc/api/examples/webpagewizard/webpagewizard.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..27b3b0e5821cb100bea521a9664c7af0c90b0e52
--- /dev/null
+++ b/doc/api/examples/webpagewizard/webpagewizard.cpp
@@ -0,0 +1,122 @@
+//! [0]
+#include "webpagewizard.h"
+
+#include <utils/filewizarddialog.h>
+#include <utils/qtcassert.h>
+
+#include <QtCore/QXmlStreamWriter>
+
+#include <QtGui/QGridLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPlainTextEdit>
+
+namespace MyPlugin {
+namespace Internal {
+
+//! [1]
+WebContentPageWizardPage::WebContentPageWizardPage(QWidget *parent) :
+    QWizardPage(parent),
+    m_titleLineEdit(new QLineEdit),
+    m_textEdit(new QPlainTextEdit),
+    m_complete(false)
+{
+    QGridLayout *layout = new QGridLayout(this);
+    QLabel *titleLabel = new QLabel(tr("&Title"));
+    layout->addWidget(titleLabel, 0, 0);
+    layout->addWidget(m_titleLineEdit, 0, 1);
+    QLabel *contentLabel = new QLabel(tr("&Content"));
+    layout->addWidget(contentLabel, 1, 0, 1, 1, Qt::AlignTop);
+    layout->addWidget(m_textEdit, 1, 1);
+    titleLabel->setBuddy(m_titleLineEdit);
+    contentLabel->setBuddy(m_textEdit);
+    setTitle(tr("Web Page Contents"));
+
+    connect(m_titleLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged()));
+    connect(m_textEdit, SIGNAL(textChanged()), this, SLOT(slotChanged()));
+}
+
+QString WebContentPageWizardPage::title() const
+{
+    return m_titleLineEdit->text();
+}
+
+QString WebContentPageWizardPage::contents() const
+{
+    return m_textEdit->toPlainText();
+}
+
+void WebContentPageWizardPage::slotChanged()
+{
+    const bool completeNow = !m_titleLineEdit->text().isEmpty()
+            && m_textEdit->blockCount() > 0;
+    if (completeNow != m_complete) {
+        m_complete = completeNow;
+        emit completeChanged();
+    }
+}
+
+//! [1] //! [2]
+
+WebContentWizardDialog::WebContentWizardDialog(QWidget *parent) :
+    Utils::FileWizardDialog(parent), m_contentPage(new WebContentPageWizardPage)
+{
+    addPage(m_contentPage);
+}
+
+//! [2] //! [3]
+
+WebPageWizard::WebPageWizard(const Core::BaseFileWizardParameters &parameters,
+                             QObject *parent) :
+    Core::BaseFileWizard(parameters, parent)
+{
+}
+
+QWizard *WebPageWizard::createWizardDialog(QWidget *parent,
+                                    const QString &defaultPath,
+                                    const WizardPageList &extensionPages) const
+{
+    WebContentWizardDialog *dialog = new WebContentWizardDialog(parent);
+    dialog->setPath(defaultPath);
+    foreach (QWizardPage *p, extensionPages)
+        dialog->addPage(p);
+    return dialog;
+}
+
+Core::GeneratedFiles
+    WebPageWizard::generateFiles(const QWizard *w,
+                                     QString *) const
+{
+    Core::GeneratedFiles files;
+    const WebContentWizardDialog *dialog = qobject_cast<const WebContentWizardDialog*>(w);
+    QTC_ASSERT(dialog, return files; )
+
+    const QString fileName = Core::BaseFileWizard::buildFileName(dialog->path(), dialog->fileName(), QLatin1String("html"));
+
+    Core::GeneratedFile file(fileName);
+
+    QString contents;
+    QXmlStreamWriter writer(&contents);
+    writer.setAutoFormatting(true);
+    writer.writeStartDocument();
+    writer.writeStartElement(QLatin1String("html"));
+    writer.writeStartElement(QLatin1String("head"));
+    writer.writeTextElement(QLatin1String("title"), dialog->title());
+    writer.writeEndElement(); // HEAD
+    writer.writeStartElement(QLatin1String("body"));
+    writer.writeTextElement(QLatin1String("h1"), dialog->title());
+    writer.writeTextElement(QLatin1String("p"), dialog->contents());
+    writer.writeEndElement(); // BODY
+    writer.writeEndElement(); // HTML
+    file.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
+    file.setContents(contents);
+    files.push_back(file);
+    return files;
+}
+
+//! [3]
+
+} // namespace Internal
+} // namespace MyPlugin
+
+//! [0]
diff --git a/doc/api/examples/webpagewizard/webpagewizard.h b/doc/api/examples/webpagewizard/webpagewizard.h
new file mode 100644
index 0000000000000000000000000000000000000000..a34c228856728bf784b34739ead8ca2936084a48
--- /dev/null
+++ b/doc/api/examples/webpagewizard/webpagewizard.h
@@ -0,0 +1,76 @@
+//! [0]
+
+#ifndef WEBPAGEFILEWIZARD_H
+#define WEBPAGEFILEWIZARD_H
+
+#include "basefilewizard.h"
+#include "utils/filewizarddialog.h"
+
+#include <QtGui/QWizardPage>
+
+QT_BEGIN_NAMESPACE
+class QLineEdit;
+class QPlainTextEdit;
+QT_END_NAMESPACE
+
+namespace MyPlugin {
+namespace Internal {
+
+//! [1]
+class WebContentPageWizardPage : public QWizardPage
+{
+    Q_OBJECT
+public:
+    explicit WebContentPageWizardPage(QWidget *parent = 0);
+
+    QString title() const;
+    QString contents() const;
+
+    virtual bool isComplete() const { return m_complete; }
+
+private slots:
+    void slotChanged();
+
+private:
+    QLineEdit *m_titleLineEdit;
+    QPlainTextEdit *m_textEdit;
+    bool m_complete;
+};
+
+//! [1] //! [2]
+
+class WebContentWizardDialog : public Utils::FileWizardDialog
+{
+    Q_OBJECT
+public:
+    explicit WebContentWizardDialog(QWidget *parent = 0);
+
+    QString title() const    { return m_contentPage->title(); }
+    QString contents() const { return m_contentPage->contents(); }
+
+private:
+    WebContentPageWizardPage *m_contentPage;
+};
+
+//! [2] //! [3]
+
+class WebPageWizard : public Core::BaseFileWizard
+{
+public:
+    explicit WebPageWizard(const Core::BaseFileWizardParameters &parameters,
+                           QObject *parent = 0);
+protected:
+    virtual QWizard *createWizardDialog(QWidget *parent,
+                                        const QString &defaultPath,
+                                        const WizardPageList &extensionPages) const;
+    virtual Core::GeneratedFiles generateFiles(const QWizard *w,
+                                         QString *errorMessage) const;
+};
+
+//! [3]
+} // namespace Internal
+} // namespace MyPlugin
+
+
+#endif // WEBPAGEFILEWIZARD_H
+//! [0]
diff --git a/doc/api/examples/webpagewizard/webpagewizardplugin.cpp b/doc/api/examples/webpagewizard/webpagewizardplugin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..29720c50cf33741d9c802e03375981fae980b8a3
--- /dev/null
+++ b/doc/api/examples/webpagewizard/webpagewizardplugin.cpp
@@ -0,0 +1,13 @@
+//! [0]
+bool MyPlugin::initialize(const QStringList &arguments, QString *errorMessage)
+{
+    Core::BaseFileWizardParameters p(IWizard::FileWizard);
+    p.setCategory(QLatin1String("P.web"));
+    p.setDisplayCategory(tr("Web"));
+    p.setDescription(tr("Creates a Web Page."));
+    p.setDisplayName(tr("Web Page"));
+    p.setId(QLatin1String("A.WebPage"));
+    addAutoReleasedObject(new WebPageWizard(p));
+}
+
+//! [0]
diff --git a/doc/api/qtcreator-dev-wizards.qdoc b/doc/api/qtcreator-dev-wizards.qdoc
new file mode 100644
index 0000000000000000000000000000000000000000..30bbf22751705e29486b37904b06c216c0fb1c9d
--- /dev/null
+++ b/doc/api/qtcreator-dev-wizards.qdoc
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Free Documentation License
+**
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+/*!
+    \page qtcreator-dev-wizards.html
+    \title Creating Wizards in Code
+
+    \section1 Introduction
+
+    If the functionality provided by template-based
+    \l{http://doc.qt.nokia.com/qtcreator-snapshot/creator-project-wizards.html}{custom wizards}
+    is not sufficient for your case, you can write wizards in code.
+
+    A wizard in Qt Creator is an instance of a class implementing
+    the Core::IWizard interface that is registered with ExtensionSystem::PluginManager.
+
+    Implementing wizards requires:
+    \list
+    \o Deciding on a base class:
+       \list
+       \o Core::IWizard is a very generic interface that does
+          not make any assumption about what the wizard does and
+          what its UI looks like.
+
+       \o Core::BaseFileWizard should be used for wizards that
+          generate files using a UI based on Utils::Wizard.
+       \endlist
+
+    \o Providing a set of parameters that determine how the wizard shows up
+       in the list of wizards in the  \gui{New File or Project} dialog.
+
+       When deriving from Core::IWizard, virtual functions returning the
+       values have to be implemented.
+
+       When deriving from Core::BaseFileWizard, a parameter class
+       Core::BaseFileWizardParameters needs to be passed to the constructor,
+       on which the parameters can be set. This allows for easy creation
+       of several wizard instances with slightly different parameters.
+
+    \o Implementing the wizard UI
+
+       Typically, this will be a class derived from Utils::Wizard.
+       Utils::Wizard extends QWizard with the functionality to show a progress
+       bar on the left.
+
+    \o Implementing the wizard functionality
+
+       When deriving from Core::BaseFileWizard, a list of Core::GeneratedFile
+       needs to be populated with the files and their contents.
+       \note The files are not actually written to the disk. This will be
+       done by Core::BaseFileWizard after performing overwrite checks and prompting
+       the user accordingly.
+
+    \endlist
+
+    \section2 Relevant Classes
+
+    \table
+    \header
+    \o Class
+    \o Description
+
+    \row
+    \o Core::IWizard
+    \o Qt Creator wizard interface, implementations of which are registered with
+       ExtensionSystem::PluginManager.
+
+    \row
+    \o Core::BaseFileWizard
+    \o Inherits Core::IWizard and provides a base class for generating files with a UI
+       based on QWizard.
+
+    \row
+    \o Core::BaseFileWizardParameters
+    \o Contains parameters for Core::BaseFileWizard.
+
+    \row
+    \o Core::GeneratedFile
+    \o A file as produced by Core::BaseFileWizard, containing name, contents and some
+    attributes.
+
+    \row
+    \o Utils::FileWizardPage
+    \o Introductory wizard page asking for file name and path.
+
+    \row
+    \o Utils::FileWizardDialog
+    \o A wizard dialog presenting a Utils::FileWizardPage, which can be extended
+       by custom pages.
+
+    \row
+    \o Utils::ProjectIntroPage
+    \o Introductory wizard page asking for project name and path.
+
+    \row
+    \o ProjectExplorer::BaseProjectWizardDialog
+    \o Base class for project wizard dialogs, presenting
+        a Utils::ProjectIntroPage.
+
+    \endtable
+
+    \section2 Parameters
+
+    The parameters listed below determine how the wizard shows up
+    in the list of wizards in the  \gui{New File or Project} dialog.
+
+    Wizards in Qt Creator are grouped by categories.
+
+    \table
+    \header
+    \o Type
+    \o Parameter Name
+    \o Description
+
+    \row
+    \o Core::IWizard::WizardKind
+    \o kind
+    \o Enumeration value that indicates the type of the wizard (project, class, file).
+
+    \row
+    \o QIcon
+    \o icon
+    \o Icon to show.
+
+    \row
+    \o QString
+    \o description
+    \o Descriptive text.
+
+    \row
+    \o QString
+    \o displayName
+    \o Name to be shown in the list.
+
+    \row
+    \o QString
+    \o id
+    \o Unique identifier for the wizard. It also determines the order within a category.
+
+    \row
+    \o QString
+    \o category
+    \o Identifier of the category under which the wizard is to be listed. It also
+       determines the order of the categories.
+    \
+    \row
+    \o QString
+    \o displayCategory
+    \o Description of the category.
+    \endtable
+
+    \section1 Example
+
+    \section2 Introduction
+
+    In this example, we create a wizard
+    for writing HTML files consisting of a title and a paragraph,
+    making use of QXmlStreamWriter.
+
+    For the UI, we use Utils::FileWizardDialog and extend it by a page
+    letting the user enter title and contents.
+
+    In our BaseFileWizard implementation, we create the file contents
+    using QXmlStreamWriter.
+
+    \section2 The WebContentPageWizardPage Class
+
+    Let us start with the wizard page. We use a QLineEdit for the title
+    and a QPlainTextEdit for the content, arranged in a QGridLayout with
+    descriptive labels.
+    \note The QGridLayout was chosen to be able to accommodate the large
+    vertical span of the QPlainTextEdit. For standard controls, a
+    QFormLayout should be considered, which will lay out the labels
+    according to the platform guide lines.
+
+    On top of that, we implement validation logic to ensure content is entered.
+    We implement QWizardPage::isComplete() to return true when both input widgets
+    have contents, enabling the \gui{Next} button. For this to happen
+    as the user enters text, we need to connect to the changed() signal of the
+    controls and emit QWizardPage::completeChanged() once the complete status changes.
+
+    \snippet webpagewizard/webpagewizard.h 1
+
+    \snippet webpagewizard/webpagewizard.cpp 1
+
+    \section2 The WebContentWizardDialog Class
+
+    The wizard dialog extends Utils::FileWizardDialog, which presents an
+    introductory page asking for file name and path.
+    We add our WebContentPageWizardPage after that.
+
+    \snippet webpagewizard/webpagewizard.h 2
+
+    \snippet webpagewizard/webpagewizard.cpp 2
+
+    \section2 The WebContentWizard Class
+
+    In our implementation of Core::BaseFileWizard, we overwrite
+    createWizardDialog() to return an instance of our WebContentWizardDialog,
+    initially set to the path passed in. We also add the extension pages
+    we receive. Extension pages are for example the wizard pages asking for
+    a project to add the files to and whether to add the files to a version control
+    system.
+
+    In generateFiles(), we obtain the parameters from our wizard and populate
+    the list of Core::GeneratedFile with our file. To generate the contents,
+    we use QXmlStreamWriter.
+
+    \snippet webpagewizard/webpagewizard.h 3
+
+    \snippet webpagewizard/webpagewizard.cpp 3
+
+    \section2 Plugin Registration
+
+    In order for the wizard to be found by the \gui{New} dialog, we need to
+    register it with ExtensionSystem::PluginManager, which also takes care
+    of deleting it:
+
+    \snippet webpagewizard/webpagewizardplugin.cpp 0
+
+    \section2 Complete Example Code
+
+    Here is the complete code of \c webpagewizard.h:
+    \snippet webpagewizard/webpagewizard.h 0
+    The complete code of \c webpagewizard.cpp looks as follows:
+    \snippet webpagewizard/webpagewizard.cpp 0
+
+    The registration of the wizard in the \c initialize() method
+    of a plugin looks like:
+    \snippet webpagewizard/webpagewizardplugin.cpp 0
+*/
diff --git a/doc/api/qtcreator-dev.qdoc b/doc/api/qtcreator-dev.qdoc
index ee66c5557a26efd569d395d1ebba3495f5685dad..c11b7ecb9c3e63028d4c17eb3504b1173f511a43 100644
--- a/doc/api/qtcreator-dev.qdoc
+++ b/doc/api/qtcreator-dev.qdoc
@@ -80,7 +80,7 @@
     \list
     \o \l{Creating Plugins}
     \o \l{Qt Creator Coding Rules}
-    \o \l{Wizards}
+    \o \l{Creating Wizards in Code}
     \o \l{User Interface Text Guidelines}
     \endlist
 
diff --git a/doc/config/qtcreator-developer.qdocconf b/doc/config/qtcreator-developer.qdocconf
index eac89aad7c051c3616046a439838ff241ec87817..343a06a8b98c37df630b73eb1cb9116c53e67aca 100644
--- a/doc/config/qtcreator-developer.qdocconf
+++ b/doc/config/qtcreator-developer.qdocconf
@@ -39,7 +39,7 @@ sources.fileextensions  = "*.cpp *.qdoc"
 
 imagedirs = $SRCDIR/images $SRCDIR/templates/images
 outputdir = ../api/html
-exampledirs = 
+exampledirs = ../api/examples
 indexes                 = qt.index
 
 include(compat.qdocconf)