diff --git a/app/assets/icons/video.svg b/app/assets/icons/video.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4acd2bbfa5ad16698ec8b0c6e867af635de8c9c7
--- /dev/null
+++ b/app/assets/icons/video.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M10,8V16L15,12L10,8Z" /></svg>
\ No newline at end of file
diff --git a/app/components/elements/Icon.jsx b/app/components/elements/Icon.jsx
index a1ada971770c6fb34cb306b63238a60600065a73..07ca9b7b0fa05882d51047370100805f036a02c7 100644
--- a/app/components/elements/Icon.jsx
+++ b/app/components/elements/Icon.jsx
@@ -30,6 +30,7 @@ const icons = [
     'reblog',
     'photo',
     'line',
+    'video',
 ];
 const icons_map = {};
 for (const i of icons) icons_map[i] = require(`app/assets/icons/${i}.svg`);
diff --git a/app/components/elements/SlateEditor.jsx b/app/components/elements/SlateEditor.jsx
index 5b6d022f34ae04c5acc0003f58e0f28454b06951..5cd6a75b0fe967cfd8a5927003cd417c87599f9a 100644
--- a/app/components/elements/SlateEditor.jsx
+++ b/app/components/elements/SlateEditor.jsx
@@ -367,6 +367,7 @@ console.log(JSON.stringify(Raw.serialize(state, {terse: false}), null, 2))
             <Portal isOpened onOpen={this.onSidebarOpen}>
                 <div className="SlateEditor__sidebar">
                     {this.renderAddBlockButton({type: 'image', label: <Icon name="photo" />, handler: this.onClickInsertImage})}
+                    {this.renderAddBlockButton({type: 'video', label: <Icon name="video" />, handler: this.onClickInsertVideo})}
                     {this.renderAddBlockButton({type: 'hrule', label: <Icon name="line" />, handler: this.onClickInsertHr})}
                 </div>
             </Portal>
@@ -383,8 +384,22 @@ console.log(JSON.stringify(Raw.serialize(state, {terse: false}), null, 2))
         state = state
             .transform()
             .insertInline({type: 'image', isVoid: true, data: {src}})
-            .insertBlock({type: 'paragraph', isVoid: false, nodes: [Slate.Text.create()]})
+            //.insertBlock({type: 'paragraph', isVoid: false, nodes: [Slate.Text.create()]})
             .focus()
+            .collapseToEndOfNextBlock()
+            .apply()
+
+        this.setState({ state })
+    }
+
+    onClickInsertVideo = (e, type) => {
+        e.preventDefault()
+        let { state } = this.state
+
+        state = state
+            .transform()
+            .insertBlock({type: 'embed', isVoid: true, data: {src: 'https://www.youtube.com/watch?v=7YOozVnEdFQ'}})
+            .insertBlock({type: 'paragraph', isVoid: false})
             .apply()
 
         this.setState({ state })
diff --git a/app/components/elements/SlateEditor.scss b/app/components/elements/SlateEditor.scss
index 675f4cd94fe6df0ac2343717412d9ee9d8b2dcaf..09eb18385c7cea21f92665d33512c913990114a1 100644
--- a/app/components/elements/SlateEditor.scss
+++ b/app/components/elements/SlateEditor.scss
@@ -4,6 +4,7 @@
     position: relative;
     img {border: 1px dotted #00f}
   }
+  div.active,
   img.active {box-shadow: 0 0 2px 1px #48C;}
   hr.active {box-shadow: 0 0 2px 1px #48C;}
 
diff --git a/app/utils/SlateEditor/Iframe.js b/app/utils/SlateEditor/Iframe.js
new file mode 100644
index 0000000000000000000000000000000000000000..57b1c4831705cd57dd0ce8811f57e2a3af9b5480
--- /dev/null
+++ b/app/utils/SlateEditor/Iframe.js
@@ -0,0 +1,103 @@
+import React from 'react'
+import linksRe from 'app/utils/Links'
+
+export default class Iframe extends React.Component {
+
+    normalizeEmbedUrl = (url) => {
+        // Detect youtube URLs
+        const match = url.match(linksRe.youTubeId)
+        if(match && match.length >= 2) {
+            return 'https://www.youtube.com/embed/' + match[1]
+        }
+
+        console.log("unable to auto-detect embed url", url)
+        return null
+    }
+
+    onChange = (e) => {
+        const { node, state, editor } = this.props
+        const value = e.target.value
+
+        const src = this.normalizeEmbedUrl(value) || value
+
+        const next = editor
+            .getState()
+            .transform()
+            .setNodeByKey(node.key, {data: {src}})
+            .apply()
+
+        editor.onChange(next)
+    }
+
+    onClick = (e) => {
+        // stop propagation so that the void node itself isn't focused, since that would unfocus the input.
+        e.stopPropagation()
+    }
+
+    render = () => {
+        const { node, state, attributes } = this.props
+        const isFocused = state.selection.hasEdgeIn(node)
+        const className = isFocused ? 'active' : null
+        const style = {background: 'black', color: 'white'}
+
+        return (
+            <div {...attributes} className={className} style={style}>
+                {this.renderFrame()}
+                Embed URL: {this.renderInput()}
+            </div>
+        )
+    }
+
+    renderFrame = () => {
+        let src = this.props.node.data.get('src')
+        src = this.normalizeEmbedUrl(src) || src
+
+        const aspectStyle = {
+            position: 'relative',
+            paddingBottom: '56.2%',
+            height: '0'
+        }
+        const lockStyle = {
+            position: 'absolute',
+            top: '0px',
+            left: '0px',
+            width: '100%',
+            height: '100%',
+            background: 'rgba(0,0,0,0.1)'
+        }
+        const style = {
+            position: 'absolute',
+            top: '0px',
+            left: '0px',
+            width: '100%',
+            height: '100%'
+        }
+
+        return (
+            <div style={aspectStyle}>
+                <iframe
+                  type="text/html"
+                  width="640"
+                  height="360"
+                  src={src}
+                  frameBorder="0"
+                  style={style}>
+                </iframe>
+                <div style={lockStyle}></div>
+            </div>
+        )
+    }
+
+    renderInput = () => {
+        const src = this.props.node.data.get('src')
+        return (
+            <input
+              value={src}
+              onChange={this.onChange}
+              onClick={this.onClick}
+              style={{ marginTop: '5px', background: 'black' }}
+              size="70"
+            />
+        )
+    }
+}
diff --git a/app/utils/SlateEditor/Schema.js b/app/utils/SlateEditor/Schema.js
index 048cb1d3146e0a716e79789312677f3fb0cefede..2b103cfd979d204db71d88d7c5bc74682845b601 100644
--- a/app/utils/SlateEditor/Schema.js
+++ b/app/utils/SlateEditor/Schema.js
@@ -1,6 +1,7 @@
 import React from 'react'
 import Link from 'app/utils/SlateEditor/Link'
 import Image from 'app/utils/SlateEditor/Image'
+import Iframe from 'app/utils/SlateEditor/Iframe'
 import HRule from 'app/utils/SlateEditor/HRule'
 
 
@@ -211,6 +212,7 @@ export const schema = {
         'hr':    HRule,
         'image': Image,
         'link':  Link,
+        'embed': Iframe,
     },
 
     marks: {