diff --git a/CHANGELOG b/CHANGELOG
index b929f1fd7b932ded817c9c72ba5ddf368b5f9a3e..3f963e039be5220785f647d8104c678a82e645c6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -31,6 +31,8 @@ v 8.7.0 (unreleased)
   - Fix a bug whith trailing slash in teamcity_url (Charles May)
   - Allow back dating on issues when created or updated through the API
   - Allow back dating on issue notes when created through the API
+  - Propose license template when creating a new LICENSE file
+  - API: Expose /licenses and /licenses/:key
   - Fix avatar stretching by providing a cropping feature
   - API: Expose `subscribed` for issues and merge requests (Robert Schilling)
   - Allow SAML to handle external users based on user's information !3530
diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index f4757658d54463d7e8762586a417cb7717536c99..dd1bbb37551e805b43c4e0700a04a498169edc2a 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -93,17 +93,15 @@
     ).done (projects) ->
       callback(projects)
 
-  # Return text for specific license
-  licenseText: (key, fullname, callback) ->
-    url = Api.buildUrl(Api.license_path)
-    url = url.replace(':key', key)
+  # Return text for a specific license
+  licenseText: (key, data, callback) ->
+    url = Api.buildUrl(Api.license_path).replace(':key', key)
 
     $.ajax(
       url: url
-      data:
-        fullname: fullname
-    ).done (projects) ->
-      callback(projects)
+      data: data
+    ).done (license) ->
+      callback(license)
 
   buildUrl: (url) ->
     url = gon.relative_url_root + url if gon.relative_url_root?
diff --git a/app/assets/javascripts/blob/blob_license_selector.js.coffee b/app/assets/javascripts/blob/blob_license_selector.js.coffee
index b43c1ec2bb5834d606b0ea5859b6c457dfe01cb4..e17eaa75dc11274c455593bd77e0887de39165d8 100644
--- a/app/assets/javascripts/blob/blob_license_selector.js.coffee
+++ b/app/assets/javascripts/blob/blob_license_selector.js.coffee
@@ -1,24 +1,30 @@
 class @BlobLicenseSelector
   licenseRegex: /^(.+\/)?(licen[sc]e|copying)($|\.)/i
 
-  constructor: (editor)->
-    self = this
-    @licenseSelector = $('.js-license-selector')
-    @toggleLicenseSelector($('#file_name').val())
+  constructor: (editor) ->
+    @$licenseSelector = $('.js-license-selector')
+    $fileNameInput = $('#file_name')
 
-    $('#file_name').on 'input', ->
-      self.toggleLicenseSelector($(this).val())
+    initialFileNameValue = if $fileNameInput.length
+      $fileNameInput.val()
+    else if $('.editor-file-name').length
+      $('.editor-file-name').text().trim()
 
-    $('select.license-select').select2(
-      width: 'resolve'
-      dropdownAutoWidth: true
-      placeholder: 'Choose a license template'
-    ).on 'change', (e) ->
-      Api.licenseText $(this).val(), $(this).data('fullname'), (data) ->
-        editor.setValue(data, -1)
+    @toggleLicenseSelector(initialFileNameValue)
+
+    if $fileNameInput
+      $fileNameInput.on 'keyup blur', (e) =>
+        @toggleLicenseSelector($(e.target).val())
+
+    $('select.license-select').on 'change', (e) ->
+      data =
+        project: $(this).data('project')
+        fullname: $(this).data('fullname')
+      Api.licenseText $(this).val(), data, (license) ->
+        editor.setValue(license.content, -1)
 
   toggleLicenseSelector: (fileName) =>
     if @licenseRegex.test(fileName)
-      @licenseSelector.show()
+      @$licenseSelector.show()
     else
-      @licenseSelector.hide()
+      @$licenseSelector.hide()
diff --git a/app/assets/javascripts/blob/edit_blob.js.coffee b/app/assets/javascripts/blob/edit_blob.js.coffee
index 390e41ed8d4ca56ee8bfb9b2ad16e724e2cbe7e9..eea9aa972ee33715cf217579640065095300462b 100644
--- a/app/assets/javascripts/blob/edit_blob.js.coffee
+++ b/app/assets/javascripts/blob/edit_blob.js.coffee
@@ -1,44 +1,39 @@
 class @EditBlob
-  constructor: (assets_path, mode)->
-    ace.config.set "modePath", assets_path + '/ace'
+  constructor: (assets_path, ace_mode = null) ->
+    ace.config.set "modePath", "#{assets_path}/ace"
     ace.config.loadModule "ace/ext/searchbox"
-    if mode
-      ace_mode = mode
-    editor = ace.edit("editor")
-    editor.focus()
-    @editor = editor
-
-    if ace_mode
-      editor.getSession().setMode "ace/mode/" + ace_mode
+    @editor = ace.edit("editor")
+    @editor.focus()
+    @editor.getSession().setMode "ace/mode/#{ace_mode}" if ace_mode
 
     # Before a form submission, move the content from the Ace editor into the
     # submitted textarea
-    $('form').submit ->
-      $("#file-content").val(editor.getValue())
+    $('form').submit =>
+      $("#file-content").val(@editor.getValue())
+
+    @initModePanesAndLinks()
+    new BlobLicenseSelector(@editor)
 
-    editModePanes = $(".js-edit-mode-pane")
-    editModeLinks = $(".js-edit-mode a")
-    editModeLinks.click (event) ->
-      event.preventDefault()
-      currentLink = $(this)
-      paneId = currentLink.attr("href")
-      currentPane = editModePanes.filter(paneId)
-      editModeLinks.parent().removeClass "active hover"
-      currentLink.parent().addClass "active hover"
-      editModePanes.hide()
-      if paneId is "#preview"
-        currentPane.fadeIn 200
-        $.post currentLink.data("preview-url"),
-          content: editor.getValue()
-        , (response) ->
-          currentPane.empty().append response
-          currentPane.syntaxHighlight()
-          return
+  initModePanesAndLinks: ->
+    @$editModePanes = $(".js-edit-mode-pane")
+    @$editModeLinks = $(".js-edit-mode a")
+    @$editModeLinks.click @editModeLinkClickHandler
 
-      else
-        currentPane.fadeIn 200
-        editor.focus()
-      return
+  editModeLinkClickHandler: (event) =>
+    event.preventDefault()
+    currentLink = $(event.target)
+    paneId = currentLink.attr("href")
+    currentPane = @$editModePanes.filter(paneId)
+    @$editModeLinks.parent().removeClass "active hover"
+    currentLink.parent().addClass "active hover"
+    @$editModePanes.hide()
+    currentPane.fadeIn 200
+    if paneId is "#preview"
+      $.post currentLink.data("preview-url"),
+        content: @editor.getValue()
+      , (response) ->
+        currentPane.empty().append response
+        currentPane.syntaxHighlight()
 
-  editor: ->
-    return @editor
+    else
+      @editor.focus()
diff --git a/app/assets/javascripts/blob/new_blob.js.coffee b/app/assets/javascripts/blob/new_blob.js.coffee
deleted file mode 100644
index 68c5e5195e396b5ef3a38ce187be52535037133c..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/blob/new_blob.js.coffee
+++ /dev/null
@@ -1,20 +0,0 @@
-class @NewBlob
-  constructor: (assets_path, mode)->
-    ace.config.set "modePath", assets_path + '/ace'
-    ace.config.loadModule "ace/ext/searchbox"
-    if mode
-      ace_mode = mode
-    editor = ace.edit("editor")
-    editor.focus()
-    @editor = editor
-
-    if ace_mode
-      editor.getSession().setMode "ace/mode/" + ace_mode
-
-    # Before a form submission, move the content from the Ace editor into the
-    # submitted textarea
-    $('form').submit ->
-      $("#file-content").val(editor.getValue())
-
-  editor: ->
-    return @editor
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 6960562d15ff1981647072253b27a8d379abb4e1..cd8b2911674b78cac69bdee0835f5da98e0f5a22 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -122,15 +122,6 @@ class Projects::BlobController < Projects::ApplicationController
   end
 
   def editor_variables
-    @licenses = {
-      'Popular' => Licensee::License.all(featured: true).map!{ |license| [license.name, license.key] },
-      'Other' => Licensee::License.all(featured: false).map!{ |license| [license.name, license.key] }
-    }
-
-    unless @repository.empty?
-      @current_license_key = Licensee.license(@repository.path).try(:key)
-    end
-
     @target_branch = params[:target_branch]
 
     @file_path =
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 9e59a295fc469fa39f01b68e585b69412af822b9..a4d7c425d0f359b192bc8e526b957926f2b82d23 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -173,4 +173,15 @@ module BlobHelper
     response.etag = @blob.id
     !stale
   end
+
+  def licenses_for_select
+    return @licenses_for_select if defined?(@licenses_for_select)
+
+    licenses = Licensee::License.all
+
+    @licenses_for_select = {
+      Popular: licenses.select(&:featured).map { |license| [license.name, license.key] },
+      Other: licenses.reject(&:featured).map { |license| [license.name, license.key] }
+    }
+  end
 end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 0b0cb658b1781cc84f3bc00a8b24dfdaaee1252a..81be73937a9ce29469acb7af8176de3d1a807cef 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -216,40 +216,14 @@ module ProjectsHelper
     end
   end
 
-  def add_contribution_guide_path(project)
-    if project && !project.repository.contribution_guide
-      namespace_project_new_blob_path(
-        project.namespace,
-        project,
-        project.default_branch,
-        file_name:      "CONTRIBUTING.md",
-        commit_message: "Add contribution guide"
-      )
-    end
-  end
-
-  def add_changelog_path(project)
-    if project && !project.repository.changelog
-      namespace_project_new_blob_path(
-        project.namespace,
-        project,
-        project.default_branch,
-        file_name:      "CHANGELOG",
-        commit_message: "Add changelog"
-      )
-    end
-  end
-
-  def add_license_path(project)
-    if project && !project.repository.license
-      namespace_project_new_blob_path(
-        project.namespace,
-        project,
-        project.default_branch,
-        file_name:      "LICENSE",
-        commit_message: "Add license"
-      )
-    end
+  def add_special_file_path(project, file_name:, commit_message: nil)
+    namespace_project_new_blob_path(
+      project.namespace,
+      project,
+      project.default_branch || 'master',
+      file_name:      file_name,
+      commit_message: commit_message || "Add #{file_name.downcase}"
+    )
   end
 
   def contribution_guide_path(project)
@@ -272,7 +246,7 @@ module ProjectsHelper
   end
 
   def license_path(project)
-    filename_path(project, :license)
+    filename_path(project, :license_blob)
   end
 
   def version_path(project)
@@ -342,6 +316,12 @@ module ProjectsHelper
     @ref || @repository.try(:root_ref)
   end
 
+  def license_short_name(project)
+    license = Licensee::License.new(project.repository.license_key)
+
+    license.nickname || license.name
+  end
+
   private
 
   def filename_path(project, filename)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 589756f853126647bcb4bcaa36aef1d635a8e83b..5d6fe017b5e0aa2d3a74eb1b41b7337d5344472b 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -228,7 +228,8 @@ class Repository
 
   def cache_keys
     %i(size branch_names tag_names commit_count
-       readme version contribution_guide changelog license)
+       readme version contribution_guide changelog
+       license_blob license_key)
   end
 
   def build_cache
@@ -461,27 +462,21 @@ class Repository
     end
   end
 
-  def license
-    cache.fetch(:license) do
-      licenses =  tree(:head).blobs.find_all do |file|
-                    file.name =~ /\A(copying|license|licence)/i
-                  end
-
-      preferences = [
-        /\Alicen[sc]e\z/i,        # LICENSE, LICENCE
-        /\Alicen[sc]e\./i,        # LICENSE.md, LICENSE.txt
-        /\Acopying\z/i,           # COPYING
-        /\Acopying\.(?!lesser)/i, # COPYING.txt
-        /Acopying.lesser/i        # COPYING.LESSER
-      ]
+  def license_blob
+    return nil if !exists? || empty?
 
-      license = nil
-      preferences.each do |r|
-        license = licenses.find { |l| l.name =~ r }
-        break if license
+    cache.fetch(:license_blob) do
+      if licensee_project.license
+        blob_at_branch(root_ref, licensee_project.matched_file.filename)
       end
+    end
+  end
 
-      license
+  def license_key
+    return nil if !exists? || empty?
+
+    cache.fetch(:license_key) do
+      licensee_project.license.try(:key) || 'no-license'
     end
   end
 
@@ -925,4 +920,8 @@ class Repository
   def cache
     @cache ||= RepositoryCache.new(path_with_namespace)
   end
+
+  def licensee_project
+    @licensee_project ||= Licensee.project(path)
+  end
 end
diff --git a/app/views/projects/_readme.html.haml b/app/views/projects/_readme.html.haml
index d1191928d4fd36811b80baa02cccbb4c09cc6961..a9908eaeccaf0c5f95806c65e36b57cd2662788e 100644
--- a/app/views/projects/_readme.html.haml
+++ b/app/views/projects/_readme.html.haml
@@ -9,7 +9,7 @@
 - else
   .gray-content-block.second-block.center
     %h3.page-title
-      This project does not have README yet
+      This project does not have a README yet
     - if can?(current_user, :push_code, @project)
       %p
         A
@@ -18,5 +18,5 @@
         distributed with computer software, forming part of its documentation.
       %p
         We recommend you to
-        = link_to "add README", new_readme_path, class: 'underlined-link'
+        = link_to "add a README", new_readme_path, class: 'underlined-link'
         file to the repository and GitLab will render it here instead of this message.
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 8ebbc91f81d2b68c1d48b70709caf50261605da9..fefa652a3da9ccd9350e58bab8b24a065fbb1095 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -14,7 +14,7 @@
 
     .pull-right
       .license-selector.js-license-selector.hide
-        = select_tag :license_type, grouped_options_for_select(@licenses, @current_license_key), include_blank: true, class: 'select2 license-select', data: { fullname: @repository.project.creator.name }
+        = select_tag :license_type, grouped_options_for_select(licenses_for_select, @project.repository.license_key), include_blank: true, class: 'select2 license-select', data: {placeholder: 'Choose a license template', project: @project.name, fullname: @project.namespace.human_name}
 
       .encoding-selector
         = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2'
@@ -26,8 +26,3 @@
         .center
           %h2
             %i.icon-spinner.icon-spin
-
-:javascript
-  window.onload = function() {
-    new BlobLicenseSelector(blob.editor)
-  }
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index 1dd2b5c0af76a209a2e3314cad0cbf0d9ba57626..0459699432e8b985f48d0460621543a1277897aa 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -14,5 +14,5 @@
               cancel_path: namespace_project_tree_path(@project.namespace, @project, @id)
 
 :javascript
-  blob = new NewBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", null)
+  blob = new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}")
   new NewCommitForm($('.js-new-blob-form'))
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 2eb79703304d8c95a6165dbe2c5e869b4835ac24..52d093871b40f8f78ed35ead662940863a6010fa 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -14,10 +14,10 @@
     %p
       If you already have files you can push them using command line instructions below.
     %p
-      Otherwise you can start with adding
+      Otherwise you can start with adding a
       = link_to "README", new_readme_path, class: 'underlined-link'
-      or
-      = link_to "LICENSE", new_license_path, class: 'underlined-link'
+      or a
+      = link_to "LICENSE", add_special_file_path(@project, file_name: 'LICENSE'), class: 'underlined-link'
       file to this project.
 
 - if can?(current_user, :push_code, @project)
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 4310f038fc94e5b083c3713253218325759d8ea7..d854ac217256b8c042e1abda2793f34d8f1455e7 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -36,9 +36,9 @@
       %li
         = link_to 'Changelog', changelog_path(@project)
 
-    - if @repository.license
+    - if @repository.license_blob
       %li
-        = link_to 'License', license_path(@project)
+        = link_to license_short_name(@project), license_path(@project)
 
     - if @repository.contribution_guide
       %li
@@ -47,15 +47,15 @@
     - if current_user && can_push_branch?(@project, @project.default_branch)
       - unless @repository.changelog
         %li.missing
-          = link_to add_changelog_path(@project) do
+          = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
             Add Changelog
-      - unless @repository.license
+      - unless @repository.license_blob
         %li.missing
-          = link_to add_license_path(@project) do
+          = link_to add_special_file_path(@project, file_name: 'LICENSE') do
             Add License
       - unless @repository.contribution_guide
         %li.missing
-          = link_to add_contribution_guide_path(@project) do
+          = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
             Add Contribution guide
 
 - if @repository.commit
diff --git a/doc/api/README.md b/doc/api/README.md
index 3a8fa6cebd1d475ec3b9e0059309474e88a2a0b5..ff039f1886f161a2a1a97ba2b7fa6670ed6a465c 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -33,6 +33,7 @@ following locations:
 - [Build triggers](build_triggers.md)
 - [Build Variables](build_variables.md)
 - [Runners](runners.md)
+- [Licenses](licenses.md)
 
 ## Authentication
 
diff --git a/doc/api/licenses.md b/doc/api/licenses.md
new file mode 100644
index 0000000000000000000000000000000000000000..855b0eab56fe265fdad31585f8ed8e4dade28bd0
--- /dev/null
+++ b/doc/api/licenses.md
@@ -0,0 +1,147 @@
+# Licenses
+
+## List license templates
+
+Get all license templates.
+
+```
+GET /licenses
+```
+
+| Attribute | Type    | Required | Description           |
+| --------- | ------- | -------- | --------------------- |
+| `popular` | boolean | no       | If passed, returns only popular licenses |
+
+```bash
+curl https://gitlab.example.com/api/v3/licenses?popular=1
+```
+
+Example response:
+
+```json
+[
+    {
+        "key": "apache-2.0",
+        "name": "Apache License 2.0",
+        "nickname": null,
+        "featured": true,
+        "html_url": "http://choosealicense.com/licenses/apache-2.0/",
+        "source_url": "http://www.apache.org/licenses/LICENSE-2.0.html",
+        "description": "A permissive license that also provides an express grant of patent rights from contributors to users.",
+        "conditions": [
+            "include-copyright",
+            "document-changes"
+        ],
+        "permissions": [
+            "commercial-use",
+            "modifications",
+            "distribution",
+            "patent-use",
+            "private-use"
+        ],
+        "limitations": [
+            "trademark-use",
+            "no-liability"
+        ],
+        "content": "                                 Apache License\n                           Version 2.0, January 2004\n [...]"
+    },
+    {
+        "key": "gpl-3.0",
+        "name": "GNU General Public License v3.0",
+        "nickname": "GNU GPLv3",
+        "featured": true,
+        "html_url": "http://choosealicense.com/licenses/gpl-3.0/",
+        "source_url": "http://www.gnu.org/licenses/gpl-3.0.txt",
+        "description": "The GNU GPL is the most widely used free software license and has a strong copyleft requirement. When distributing derived works, the source code of the work must be made available under the same license.",
+        "conditions": [
+            "include-copyright",
+            "document-changes",
+            "disclose-source",
+            "same-license"
+        ],
+        "permissions": [
+            "commercial-use",
+            "modifications",
+            "distribution",
+            "patent-use",
+            "private-use"
+        ],
+        "limitations": [
+            "no-liability"
+        ],
+        "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n [...]"
+    },
+    {
+        "key": "mit",
+        "name": "MIT License",
+        "nickname": null,
+        "featured": true,
+        "html_url": "http://choosealicense.com/licenses/mit/",
+        "source_url": "http://opensource.org/licenses/MIT",
+        "description": "A permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty.",
+        "conditions": [
+            "include-copyright"
+        ],
+        "permissions": [
+            "commercial-use",
+            "modifications",
+            "distribution",
+            "private-use"
+        ],
+        "limitations": [
+            "no-liability"
+        ],
+        "content": "The MIT License (MIT)\n\nCopyright (c) [year] [fullname]\n [...]"
+    }
+]
+```
+
+## Single license template
+
+Get a single license template. You can pass parameters to replace the license
+placeholder.
+
+```
+GET /licenses/:key
+```
+
+| Attribute  | Type   | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `key`      | string | yes      | The key of the license template |
+| `project`  | string | no       | The copyrighted project name |
+| `fullname` | string | no       | The full-name of the copyright holder |
+
+>**Note:**
+If you omit the `fullname` parameter but authenticate your request, the name of
+the authenticated user will be used to replace the copyright holder placeholder.
+
+```bash
+curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/licenses/mit?project=My+Cool+Project
+```
+
+Example response:
+
+```json
+{
+    "key": "mit",
+    "name": "MIT License",
+    "nickname": null,
+    "featured": true,
+    "html_url": "http://choosealicense.com/licenses/mit/",
+    "source_url": "http://opensource.org/licenses/MIT",
+    "description": "A permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty.",
+    "conditions": [
+        "include-copyright"
+    ],
+    "permissions": [
+        "commercial-use",
+        "modifications",
+        "distribution",
+        "private-use"
+    ],
+    "limitations": [
+        "no-liability"
+    ],
+    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 John Doe\n [...]"
+}
+```
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 60b9f5e0eceeebbd37278e76cf04fa40fb531c2c..61df948df60cd2b32ca45ce5654a876e7c8f8507 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -439,5 +439,16 @@ module API
     class Variable < Grape::Entity
       expose :key, :value
     end
+
+    class License < Grape::Entity
+      expose :key, :name, :nickname, :featured
+      expose :url, as: :html_url
+      expose(:source_url) { |license| license.meta['source'] }
+      expose(:description) { |license| license.meta['description'] }
+      expose(:conditions) { |license| license.meta['required'] }
+      expose(:permissions) { |license| license.meta['permitted'] }
+      expose(:limitations) { |license| license.meta['forbidden'] }
+      expose :content
+    end
   end
 end
diff --git a/lib/api/licenses.rb b/lib/api/licenses.rb
index 7fffbef84e4dc9763dbfb82f86405c7e5695a1f6..dac29df30f93720960319dbb4dfdefa6018e013a 100644
--- a/lib/api/licenses.rb
+++ b/lib/api/licenses.rb
@@ -1,27 +1,58 @@
 module API
   # Licenses API
   class Licenses < Grape::API
-    YEAR_TEMPLATE_REGEX = /(\[|<|{)(year|yyyy)(\]|>|})/
-    FULLNAME_TEMPLATE_REGEX = /\[fullname\]/
+    PROJECT_TEMPLATE_REGEX =
+    /[\<\{\[]
+      (project|description|
+      one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
+    [\>\}\]]/xi
+    YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i
+    FULLNAME_TEMPLATE_REGEX =
+    /[\<\{\[]
+      (fullname|name\sof\s(author|copyright\sowner))
+    [\>\}\]]/xi
+
+    # Get the list of the available license templates
+    #
+    # Parameters:
+    #   popular - Filter licenses to only the popular ones
+    #
+    # Example Request:
+    #   GET /licenses
+    #   GET /licenses?popular=1
+    get 'licenses' do
+      options = {
+        featured: params[:popular].present? ? true : nil
+      }
+      present Licensee::License.all(options), with: Entities::License
+    end
 
     # Get text for specific license
     #
     # Parameters:
     #   key (required) - The key of a license
-    #   fullname       - Reository owner fullname
+    #   project        - Copyrighted project name
+    #   fullname       - Full name of copyright holder
+    #
     # Example Request:
     #   GET /licenses/mit
-    get 'licenses/:key', requirements: { key: /[\w.-]*/ } do
-      env['api.format'] = :txt
-      license = Licensee::License.find(params[:key]).try(:text)
+    #
+    get 'licenses/:key', requirements: { key: /[\w\.-]+/ } do
+      required_attributes! [:key]
+
+      not_found!('License') unless Licensee::License.find(params[:key])
+
+      # We create a fresh Licensee::License object since we'll modify its
+      # content in place below.
+      license = Licensee::License.new(params[:key])
+
+      license.content.gsub!(YEAR_TEMPLATE_REGEX, Time.now.year.to_s)
+      license.content.gsub!(PROJECT_TEMPLATE_REGEX, params[:project]) if params[:project].present?
+
+      fullname = params[:fullname].presence || current_user.try(:name)
+      license.content.gsub!(FULLNAME_TEMPLATE_REGEX, fullname) if fullname
 
-      if license
-        license
-          .gsub(YEAR_TEMPLATE_REGEX, Time.now.year.to_s)
-          .gsub(FULLNAME_TEMPLATE_REGEX, params[:fullname])
-      else
-        error!('License not found', 404)
-      end
+      present license, with: Entities::License
     end
   end
 end
diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c0fcfd069321785f8b525dd357cc18a38b92cf1a
--- /dev/null
+++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+feature 'creates a license file', feature: true, js: true do
+  include Select2Helper
+
+  let(:project_master) { create(:user) }
+  let(:project) { create(:project) }
+  background do
+    project.repository.remove_file(project_master, 'LICENSE', 'Remove LICENSE', 'master')
+    project.team << [project_master, :master]
+    login_as(project_master)
+    visit namespace_project_path(project.namespace, project)
+  end
+
+  scenario 'project master creates a license file manually from a template' do
+    visit namespace_project_tree_path(project.namespace, project, project.repository.root_ref)
+    find('.add-to-tree').click
+    click_link 'New file'
+
+    fill_in :file_name, with: 'LICENSE'
+
+    expect(page).to have_selector('.license-selector')
+
+    select2('mit', from: '#license_type')
+
+    file_content = find('.file-content')
+    expect(file_content).to have_content('The MIT License (MIT)')
+    expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
+
+    fill_in :commit_message, with: 'Add a LICENSE file', visible: true
+    click_button 'Commit Changes'
+
+    expect(current_path).to eq(
+      namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
+    expect(page).to have_content('The MIT License (MIT)')
+    expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
+  end
+
+  scenario 'project master creates a license file from the "Add license" link' do
+    click_link 'Add License'
+
+    expect(current_path).to eq(
+      namespace_project_new_blob_path(project.namespace, project, 'master'))
+    expect(find('#file_name').value).to eq('LICENSE')
+    expect(page).to have_selector('.license-selector')
+
+    select2('mit', from: '#license_type')
+
+    file_content = find('.file-content')
+    expect(file_content).to have_content('The MIT License (MIT)')
+    expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
+
+    fill_in :commit_message, with: 'Add a LICENSE file', visible: true
+    click_button 'Commit Changes'
+
+    expect(current_path).to eq(
+      namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
+    expect(page).to have_content('The MIT License (MIT)')
+    expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
+  end
+end
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6c51d00d813ed11937f8c9f0b2168f39925ff535
--- /dev/null
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+feature 'creates a license file in empty project', feature: true, js: true do
+  include Select2Helper
+
+  let(:project_master) { create(:user) }
+  let(:project) { create(:project_empty_repo) }
+  background do
+    project.team << [project_master, :master]
+    login_as(project_master)
+    visit namespace_project_path(project.namespace, project)
+  end
+
+  scenario 'project master creates a license file from a template' do
+    click_on 'LICENSE'
+
+    expect(current_path).to eq(
+      namespace_project_new_blob_path(project.namespace, project, 'master'))
+    expect(find('#file_name').value).to eq('LICENSE')
+    expect(page).to have_selector('.license-selector')
+
+    select2('mit', from: '#license_type')
+
+    file_content = find('.file-content')
+    expect(file_content).to have_content('The MIT License (MIT)')
+    expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
+
+    fill_in :commit_message, with: 'Add a LICENSE file', visible: true
+    click_button 'Commit Changes'
+
+    expect(current_path).to eq(
+      namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
+    expect(page).to have_content('The MIT License (MIT)')
+    expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
+  end
+end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index f30a21e79ae0329f3e3a1ceb3b2a6fb00ad96aba..a374c505746925cde81e86e7209186abdba6b3f8 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -135,22 +135,69 @@ describe Repository, models: true do
 
   end
 
-  describe "#license" do
+  describe '#license_blob' do
     before do
-      repository.send(:cache).expire(:license)
+      repository.send(:cache).expire(:license_blob)
+      repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'master')
     end
 
-    it 'test selection preference' do
-      files = [TestBlob.new('file'), TestBlob.new('license'), TestBlob.new('copying')]
-      expect(repository.tree).to receive(:blobs).and_return(files)
+    it 'looks in the root_ref only' do
+      repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'markdown')
+      repository.commit_file(user, 'LICENSE', Licensee::License.new('mit').content, 'Add LICENSE', 'markdown', false)
+
+      expect(repository.license_blob).to be_nil
+    end
+
+    it 'favors license file with no extension' do
+      repository.commit_file(user, 'LICENSE', Licensee::License.new('mit').content, 'Add LICENSE', 'master', false)
+      repository.commit_file(user, 'LICENSE.md', Licensee::License.new('mit').content, 'Add LICENSE.md', 'master', false)
+
+      expect(repository.license_blob.name).to eq('LICENSE')
+    end
+
+    it 'favors .md file to .txt' do
+      repository.commit_file(user, 'LICENSE.md', Licensee::License.new('mit').content, 'Add LICENSE.md', 'master', false)
+      repository.commit_file(user, 'LICENSE.txt', Licensee::License.new('mit').content, 'Add LICENSE.txt', 'master', false)
+
+      expect(repository.license_blob.name).to eq('LICENSE.md')
+    end
+
+    it 'favors LICENCE to LICENSE' do
+      repository.commit_file(user, 'LICENSE', Licensee::License.new('mit').content, 'Add LICENSE', 'master', false)
+      repository.commit_file(user, 'LICENCE', Licensee::License.new('mit').content, 'Add LICENCE', 'master', false)
+
+      expect(repository.license_blob.name).to eq('LICENCE')
+    end
+
+    it 'favors LICENSE to COPYING' do
+      repository.commit_file(user, 'LICENSE', Licensee::License.new('mit').content, 'Add LICENSE', 'master', false)
+      repository.commit_file(user, 'COPYING', Licensee::License.new('mit').content, 'Add COPYING', 'master', false)
+
+      expect(repository.license_blob.name).to eq('LICENSE')
+    end
+
+    it 'favors LICENCE to COPYING' do
+      repository.commit_file(user, 'LICENCE', Licensee::License.new('mit').content, 'Add LICENCE', 'master', false)
+      repository.commit_file(user, 'COPYING', Licensee::License.new('mit').content, 'Add COPYING', 'master', false)
+
+      expect(repository.license_blob.name).to eq('LICENCE')
+    end
+  end
+
+  describe '#license_key' do
+    before do
+      repository.send(:cache).expire(:license_key)
+      repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'master')
+    end
 
-      expect(repository.license.name).to eq('license')
+    it 'returns "no-license" when no license is detected' do
+      expect(repository.license_key).to eq('no-license')
     end
 
-    it 'also accepts licence instead of license' do
-      expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('licence')])
+    it 'returns the license key' do
+      repository.commit_file(user, 'LICENSE', Licensee::License.new('mit').content, 'Add LICENSE', 'master', false)
 
-      expect(repository.license.name).to eq('licence')
+      expect(repository.license_key).to eq('mit')
     end
   end
 
diff --git a/spec/requests/api/licenses_spec.rb b/spec/requests/api/licenses_spec.rb
index f0f8b041f6982d148236ed5fe210ad47fc146002..61a58231c54db87709e80e61a9da08c2b1cee8e0 100644
--- a/spec/requests/api/licenses_spec.rb
+++ b/spec/requests/api/licenses_spec.rb
@@ -1,45 +1,135 @@
 require 'spec_helper'
 
-describe API::API, api: true  do
+describe API::Licenses, api: true  do
   include ApiHelpers
-  describe 'GET /licenses/:key' do
-    before(:each) do
-      get api("/licenses/#{license_type}?fullname=Anton")
+
+  describe 'Entity' do
+    before { get api('/licenses/mit') }
+
+    it { expect(json_response['key']).to eq('mit') }
+    it { expect(json_response['name']).to eq('MIT License') }
+    it { expect(json_response['nickname']).to be_nil }
+    it { expect(json_response['featured']).to be true }
+    it { expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/') }
+    it { expect(json_response['source_url']).to eq('http://opensource.org/licenses/MIT') }
+    it { expect(json_response['description']).to include('A permissive license that is short and to the point.') }
+    it { expect(json_response['conditions']).to eq(%w[include-copyright]) }
+    it { expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use]) }
+    it { expect(json_response['limitations']).to eq(%w[no-liability]) }
+    it { expect(json_response['content']).to include('The MIT License (MIT)') }
+  end
+
+  describe 'GET /licenses' do
+    it 'returns a list of available license templates' do
+      get api('/licenses')
+
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.size).to eq(15)
+      expect(json_response.first['key']).to eq('agpl-3.0')
     end
 
-    context 'for mit license name' do
-      let(:license_type){ 'mit' }
+    describe 'the popular parameter' do
+      context 'with popular=1' do
+        it 'returns a list of available popular license templates' do
+          get api('/licenses?popular=1')
 
-      it 'returns MIT license text and replases template values' do
-        expect(response.body).to include('Copyright (c) 2016 Anton')
-        expect(response.body).to include('Copyright (c) 2016')
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.size).to eq(3)
+          expect(json_response.first['key']).to eq('apache-2.0')
+        end
       end
     end
+  end
 
-    context 'for gnu license name' do
-      let(:license_type){ 'gpl-3.0' }
+  describe 'GET /licenses/:key' do
+    context 'with :project and :fullname given' do
+      before do
+        get api("/licenses/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}")
+      end
+
+      context 'for the mit license' do
+        let(:license_type) { 'mit' }
 
-      it 'returns GNU license text and replases template values' do
-        expect(response.body).to include('GNU GENERAL PUBLIC LICENSE')
-        expect(response.body).to include('Copyright (C) 2016')
+        it 'returns the license text' do
+          expect(json_response['content']).to include('The MIT License (MIT)')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('Copyright (c) 2016 Anton')
+        end
       end
-    end
 
-    context 'for apache license name' do
-      let(:license_type){ 'apache-2.0' }
+      context 'for the agpl-3.0 license' do
+        let(:license_type) { 'agpl-3.0' }
 
-      it 'returns Apache license text and replases template values' do
-        expect(response.body).to include('Apache License')
-        expect(response.body).to include('Copyright 2016')
+        it 'returns the license text' do
+          expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('My Awesome Project')
+          expect(json_response['content']).to include('Copyright (C) 2016  Anton')
+        end
+      end
+
+      context 'for the gpl-3.0 license' do
+        let(:license_type) { 'gpl-3.0' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('My Awesome Project')
+          expect(json_response['content']).to include('Copyright (C) 2016  Anton')
+        end
+      end
+
+      context 'for the gpl-2.0 license' do
+        let(:license_type) { 'gpl-2.0' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('My Awesome Project')
+          expect(json_response['content']).to include('Copyright (C) 2016  Anton')
+        end
+      end
+
+      context 'for the apache-2.0 license' do
+        let(:license_type) { 'apache-2.0' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('Apache License')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('Copyright 2016 Anton')
+        end
+      end
+
+      context 'for an uknown license' do
+        let(:license_type) { 'muth-over9000' }
+
+        it 'returns a 404' do
+          expect(response.status).to eq(404)
+        end
       end
     end
 
-    context 'for mythic license name' do
-      let(:license_type){ 'muth-over9000' }
+    context 'with no :fullname given' do
+      context 'with an authenticated user' do
+        let(:user) { create(:user) }
+
+        it 'replaces the copyright owner placeholder with the name of the current user' do
+          get api('/licenses/mit', user)
 
-      it 'returns string with error' do
-        expect(response).to have_http_status(404)
-        expect(response.body).to eq 'License not found'
+          expect(json_response['content']).to include("Copyright (c) 2016 #{user.name}")
+        end
       end
     end
   end