diff --git a/src/client/app/desktop/views/pages/share.vue b/src/client/app/desktop/views/pages/share.vue
index c4ec356d9d..d20e6e864c 100644
--- a/src/client/app/desktop/views/pages/share.vue
+++ b/src/client/app/desktop/views/pages/share.vue
@@ -3,7 +3,7 @@
 	<h1>{{ this.$t('share-with', { name }) }}</h1>
 	<div>
 		<mk-signin v-if="!$store.getters.isSignedIn"/>
-		<mk-post-form v-else-if="!posted" :initial-text="text" :instant="true" @posted="posted = true"/>
+		<mk-post-form v-else-if="!posted" :initial-text="template" :instant="true" @posted="posted = true"/>
 		<p v-if="posted" class="posted"><fa icon="check"/></p>
 	</div>
 	<button v-if="posted" class="ui button" @click="close">{{ $t('@.close') }}</button>
@@ -20,9 +20,20 @@ export default Vue.extend({
 		return {
 			name: null,
 			posted: false,
-			text: new URLSearchParams(location.search).get('text')
+			text: new URLSearchParams(location.search).get('text'),
+			url: new URLSearchParams(location.search).get('url'),
+			title: new URLSearchParams(location.search).get('title'),
 		};
 	},
+	computed: {
+		template(): string {
+			let t = '';
+			if (this.title) t += `【${title}】\n`;
+			if (this.text) t += `${text}\n`;
+			if (this.url) t += `${url}`;
+			return t.trim();
+		}
+	},
 	methods: {
 		close() {
 			window.close();
diff --git a/src/client/app/mobile/views/pages/share.vue b/src/client/app/mobile/views/pages/share.vue
index 6eabbef18e..dbafc9e7ba 100644
--- a/src/client/app/mobile/views/pages/share.vue
+++ b/src/client/app/mobile/views/pages/share.vue
@@ -3,7 +3,7 @@
 	<h1>{{ $t('share-with', { name }) }}</h1>
 	<div>
 		<mk-signin v-if="!$store.getters.isSignedIn"/>
-		<mk-post-form v-else-if="!posted" :initial-text="text" :instant="true" @posted="posted = true"/>
+		<mk-post-form v-else-if="!posted" :initial-text="template" :instant="true" @posted="posted = true"/>
 		<p v-if="posted" class="posted"><fa icon="check"/></p>
 	</div>
 	<ui-button class="close" v-if="posted" @click="close">{{ $t('@.close') }}</ui-button>
@@ -20,9 +20,20 @@ export default Vue.extend({
 		return {
 			name: null,
 			posted: false,
-			text: new URLSearchParams(location.search).get('text')
+			text: new URLSearchParams(location.search).get('text'),
+			url: new URLSearchParams(location.search).get('url'),
+			title: new URLSearchParams(location.search).get('title'),
 		};
 	},
+	computed: {
+		template(): string {
+			let t = '';
+			if (this.title) t += `【${title}】\n`;
+			if (this.text) t += `${text}\n`;
+			if (this.url) t += `${url}`;
+			return t.trim();
+		}
+	},
 	methods: {
 		close() {
 			window.close();
diff --git a/src/client/assets/manifest.json b/src/client/assets/manifest.json
index 30aea9e267..895afbed36 100644
--- a/src/client/assets/manifest.json
+++ b/src/client/assets/manifest.json
@@ -43,6 +43,11 @@
 		}
 	],
 	"share_target": {
-		"url_template": "share?text=【{title}】%0A{text}%0A{url}"
+		"action": "/share/",
+		"params": {
+			"title": "title",
+			"text": "text",
+			"url": "url"
+		}
 	}
 }