diff --git a/models/repo/topic.go b/models/repo/topic.go
index ec3de869d5..71302388b9 100644
--- a/models/repo/topic.go
+++ b/models/repo/topic.go
@@ -22,7 +22,7 @@ func init() {
 	db.RegisterModel(new(RepoTopic))
 }
 
-var topicPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
+var topicPattern = regexp.MustCompile(`^[a-z0-9][-.a-z0-9]*$`)
 
 // Topic represents a topic of repositories
 type Topic struct {
diff --git a/models/repo/topic_test.go b/models/repo/topic_test.go
index 8a8728168d..aaed91bdd3 100644
--- a/models/repo/topic_test.go
+++ b/models/repo/topic_test.go
@@ -69,6 +69,7 @@ func TestAddTopic(t *testing.T) {
 func TestTopicValidator(t *testing.T) {
 	assert.True(t, repo_model.ValidateTopic("12345"))
 	assert.True(t, repo_model.ValidateTopic("2-test"))
+	assert.True(t, repo_model.ValidateTopic("foo.bar"))
 	assert.True(t, repo_model.ValidateTopic("test-3"))
 	assert.True(t, repo_model.ValidateTopic("first"))
 	assert.True(t, repo_model.ValidateTopic("second-test-topic"))
@@ -77,4 +78,5 @@ func TestTopicValidator(t *testing.T) {
 	assert.False(t, repo_model.ValidateTopic("$fourth-test,topic"))
 	assert.False(t, repo_model.ValidateTopic("-fifth-test-topic"))
 	assert.False(t, repo_model.ValidateTopic("sixth-go-project-topic-with-excess-length"))
+	assert.False(t, repo_model.ValidateTopic(".foo"))
 }
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 6cb830b6d0..c6379d0fe6 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2507,7 +2507,7 @@ tag.create_success = Tag "%s" has been created.
 topic.manage_topics = Manage Topics
 topic.done = Done
 topic.count_prompt = You cannot select more than 25 topics
-topic.format_prompt = Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
+topic.format_prompt = Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
 
 find_file.go_to_file = Go to file
 find_file.no_matching = No matching file found
diff --git a/web_src/js/features/repo-home.js b/web_src/js/features/repo-home.js
index 55a2771054..70c225b4ba 100644
--- a/web_src/js/features/repo-home.js
+++ b/web_src/js/features/repo-home.js
@@ -166,7 +166,7 @@ export function initRepoTopicBar() {
         rules: [
           {
             type: 'validateTopic',
-            value: /^[a-z0-9][a-z0-9-]{0,35}$/,
+            value: /^\s*[a-z0-9][-.a-z0-9]{0,35}\s*$/,
             prompt: topicPrompts.formatPrompt
           },
           {