diff --git a/src/web/app/common/views/components/url-preview.vue b/src/web/app/common/views/components/url-preview.vue
index 88158db84..b84634617 100644
--- a/src/web/app/common/views/components/url-preview.vue
+++ b/src/web/app/common/views/components/url-preview.vue
@@ -1,126 +1,123 @@
 <template>
-	<a :href="url" target="_blank" :title="url" v-if="!fetching">
-		<div class="thumbnail" v-if="thumbnail" :style="`background-image: url(${thumbnail})`"></div>
-		<article>
-			<header>
-				<h1>{{ title }}</h1>
-			</header>
-			<p>{{ description }}</p>
-			<footer>
-				<img class="icon" v-if="icon" :src="icon"/>
-				<p>{{ sitename }}</p>
-			</footer>
-		</article>
-	</a>
+<a class="mk-url-preview" :href="url" target="_blank" :title="url" v-if="!fetching">
+	<div class="thumbnail" v-if="thumbnail" :style="`background-image: url(${thumbnail})`"></div>
+	<article>
+		<header>
+			<h1>{{ title }}</h1>
+		</header>
+		<p>{{ description }}</p>
+		<footer>
+			<img class="icon" v-if="icon" :src="icon"/>
+			<p>{{ sitename }}</p>
+		</footer>
+	</article>
+</a>
 </template>
 
-<script lang="typescript">
-	export default {
-		props: ['url'],
-		data() {
-			return {
-				fetching: true,
-				title: null,
-				description: null,
-				thumbnail: null,
-				icon: null,
-				sitename: null
-			};
-		},
-		created() {
-			fetch('/api:url?url=' + this.url).then(res => {
-				res.json().then(info => {
-					this.title = info.title;
-					this.description = info.description;
-					this.thumbnail = info.thumbnail;
-					this.icon = info.icon;
-					this.sitename = info.sitename;
+<script lang="ts">
+import Vue from 'vue';
 
-					this.fetching = false;
-				});
+export default Vue.extend({
+	props: ['url'],
+	data() {
+		return {
+			fetching: true,
+			title: null,
+			description: null,
+			thumbnail: null,
+			icon: null,
+			sitename: null
+		};
+	},
+	created() {
+		fetch('/api:url?url=' + this.url).then(res => {
+			res.json().then(info => {
+				this.title = info.title;
+				this.description = info.description;
+				this.thumbnail = info.thumbnail;
+				this.icon = info.icon;
+				this.sitename = info.sitename;
+
+				this.fetching = false;
 			});
-		}
-	};
+		});
+	}
+});
 </script>
 
 <style lang="stylus" scoped>
-	:scope
-		display block
-		font-size 16px
+.mk-url-preview
+	display block
+	font-size 16px
+	border solid 1px #eee
+	border-radius 4px
+	overflow hidden
 
-		> a
-			display block
-			border solid 1px #eee
-			border-radius 4px
-			overflow hidden
+	&:hover
+		text-decoration none
+		border-color #ddd
 
-			&:hover
-				text-decoration none
-				border-color #ddd
+		> article > header > h1
+			text-decoration underline
 
-				> article > header > h1
-					text-decoration underline
+	> .thumbnail
+		position absolute
+		width 100px
+		height 100%
+		background-position center
+		background-size cover
 
-			> .thumbnail
-				position absolute
-				width 100px
-				height 100%
-				background-position center
-				background-size cover
+		& + article
+			left 100px
+			width calc(100% - 100px)
 
-				& + article
-					left 100px
-					width calc(100% - 100px)
+	> article
+		padding 16px
 
-			> article
-				padding 16px
+		> header
+			margin-bottom 8px
 
-				> header
-					margin-bottom 8px
+			> h1
+				margin 0
+				font-size 1em
+				color #555
 
-					> h1
-						margin 0
-						font-size 1em
-						color #555
+		> p
+			margin 0
+			color #777
+			font-size 0.8em
 
-				> p
-					margin 0
-					color #777
-					font-size 0.8em
+		> footer
+			margin-top 8px
+			height 16px
 
-				> footer
-					margin-top 8px
-					height 16px
+			> img
+				display inline-block
+				width 16px
+				height 16px
+				margin-right 4px
+				vertical-align top
 
-					> img
-						display inline-block
-						width 16px
-						height 16px
-						margin-right 4px
-						vertical-align top
+			> p
+				display inline-block
+				margin 0
+				color #666
+				font-size 0.8em
+				line-height 16px
+				vertical-align top
 
-					> p
-						display inline-block
-						margin 0
-						color #666
-						font-size 0.8em
-						line-height 16px
-						vertical-align top
+	@media (max-width 500px)
+		font-size 8px
+		border none
 
-		@media (max-width 500px)
-			font-size 8px
+		> .thumbnail
+			width 70px
 
-			> a
-				border none
+			& + article
+				left 70px
+				width calc(100% - 70px)
 
-				> .thumbnail
-					width 70px
-
-					& + article
-						left 70px
-						width calc(100% - 70px)
-
-				> article
-					padding 8px
+		> article
+			padding 8px
 
 </style>
diff --git a/src/web/app/desktop/views/components/timeline-post.vue b/src/web/app/desktop/views/components/timeline-post.vue
index f722ea334..ed0596741 100644
--- a/src/web/app/desktop/views/components/timeline-post.vue
+++ b/src/web/app/desktop/views/components/timeline-post.vue
@@ -34,6 +34,7 @@
 					<a class="reply" v-if="p.reply">%fa:reply%</a>
 					<mk-post-html :ast="p.ast" :i="$root.$data.os.i"/>
 					<a class="quote" v-if="p.repost">RP:</a>
+					<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
 				</div>
 				<div class="media" v-if="p.media">
 					<mk-images :images="p.media"/>
@@ -101,6 +102,15 @@ export default Vue.extend({
 		},
 		url(): string {
 			return `/${this.p.user.username}/${this.p.id}`;
+		},
+		urls(): string[] {
+			if (this.p.ast) {
+				return this.p.ast
+					.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
+					.map(t => t.url);
+			} else {
+				return null;
+			}
 		}
 	},
 	created() {
@@ -113,19 +123,6 @@ export default Vue.extend({
 		if (this.$root.$data.os.isSignedIn) {
 			this.connection.on('_connected_', this.onStreamConnected);
 		}
-
-		if (this.p.text) {
-			const tokens = this.p.ast;
-
-			// URLをプレビュー
-			tokens
-			.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
-			.map(t => {
-				riot.mount(this.$refs.text.appendChild(document.createElement('mk-url-preview')), {
-					url: t.url
-				});
-			});
-		}
 	},
 	beforeDestroy() {
 		this.decapture(true);