diff --git a/CHANGELOG.md b/CHANGELOG.md
index c447084e65..266525277d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,6 +42,20 @@ mongodb:
 8. master ブランチに戻す
 9. enjoy
 
+11.7.0 (2019/04/30)
+-------------------
+### Improvements
+* MisskeyPagesに ifブロック を追加
+* MisskeyPagesに テキストエリア を追加
+* MisskeyPagesに 複数行テキスト入力 を追加
+* MisskeyPagesに 投稿フォーム を追加
+* MisskeyPagesに 変換系関数 を追加
+* MisskeyPagesでボタンやスイッチなどのテキストに変数使えるように
+
+### Fixes
+* OGPのサイト名を修正
+* デザインの調整
+
 11.6.0 (2019/04/29)
 -------------------
 ### Improvements
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index e2bfb2e896..cd29135bdb 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1842,6 +1842,7 @@ dev/views/new-app.vue:
 pages:
   new-page: "ページの作成"
   edit-page: "ページの編集"
+  read-page: "ソースを表示中"
   page-created: "ページを作成しました"
   page-updated: "ページを更新しました"
   are-you-sure-delete: "このページを削除しますか?"
@@ -1866,25 +1867,50 @@ pages:
   select-type: "種類を選択"
   enter-variable-name: "変数名を決めてください"
   the-variable-name-is-already-used: "その変数名は既に使われています"
+  content-blocks: "コンテンツ"
+  input-blocks: "入力"
+  special-blocks: "特殊"
+  post-from-post-form: "この内容を投稿"
+  posted-from-post-form: "投稿しました"
   blocks:
     text: "テキスト"
+    textarea: "テキストエリア"
     section: "セクション"
     image: "画像"
     button: "ボタン"
-    input: "ユーザー入力"
-    _input:
+
+    if: "もし"
+    _if:
+      variable: "変数"
+
+    post: "投稿フォーム"
+    _post:
+      text: "内容"
+
+    textInput: "テキスト入力"
+    _textInput:
       name: "変数名"
       text: "タイトル"
       default: "デフォルト値"
-      inputType: "入力の種類"
-      _inputType:
-        string: "テキスト"
-        number: "数値"
+
+    textareaInput: "複数行テキスト入力"
+    _textareaInput:
+      name: "変数名"
+      text: "タイトル"
+      default: "デフォルト値"
+
+    numberInput: "数値入力"
+    _numberInput:
+      name: "変数名"
+      text: "タイトル"
+      default: "デフォルト値"
+
     switch: "スイッチ"
     _switch:
       name: "変数名"
       text: "タイトル"
       default: "デフォルト値"
+
     _button:
       text: "タイトル"
       action: "ボタンを押したときの動作"
@@ -1893,6 +1919,7 @@ pages:
         _dialog:
           content: "内容"
         resetRandom: "乱数をリセット"
+
   script:
     categories:
       flow: "制御"
@@ -1903,6 +1930,7 @@ pages:
       value: "値"
       fn: "関数"
       text: "テキスト操作"
+      convert: "変換"
     blocks:
       text: "テキスト"
       multiLineText: "テキスト(複数行)"
@@ -2001,8 +2029,14 @@ pages:
       _dailyRandomPick:
         arg1: "リスト"
       number: "数"
+      stringToNumber: "テキストを数値に"
+      _stringToNumber:
+        arg1: "テキスト"
+      numberToString: "数値をテキストに"
+      _numberToString:
+        arg1: "数値"
       ref: "変数"
-      in: "入力"
+      in: "引数"
       _in:
         arg1: "スロット番号"
       fn: "関数"
diff --git a/package.json b/package.json
index 4161d89e77..3afb01dc51 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
 	"name": "misskey",
 	"author": "syuilo <i@syuilo.com>",
-	"version": "11.6.0",
+	"version": "11.7.0",
 	"codename": "daybreak",
 	"repository": {
 		"type": "git",
diff --git a/src/client/app/common/scripts/aiscript.ts b/src/client/app/common/scripts/aiscript.ts
index fe9a295000..99caec8c15 100644
--- a/src/client/app/common/scripts/aiscript.ts
+++ b/src/client/app/common/scripts/aiscript.ts
@@ -26,6 +26,7 @@ import {
 	faNotEqual,
 	faDice,
 	faSortNumericUp,
+	faExchangeAlt,
 } from '@fortawesome/free-solid-svg-icons';
 import { faFlag } from '@fortawesome/free-regular-svg-icons';
 
@@ -69,11 +70,13 @@ const funcDefs = {
 	strPick:         { in: ['string', 'number'],           out: 'string',  category: 'text',       icon: faQuoteRight, },
 	strReplace:      { in: ['string', 'string', 'string'], out: 'string',  category: 'text',       icon: faQuoteRight, },
 	strReverse:      { in: ['string'],                     out: 'string',  category: 'text',       icon: faQuoteRight, },
+	stringToNumber:  { in: ['string'],                     out: 'number',  category: 'convert',    icon: faExchangeAlt, },
+	numberToString:  { in: ['number'],                     out: 'string',  category: 'convert',    icon: faExchangeAlt, },
 	rannum:          { in: ['number', 'number'],           out: 'number',  category: 'random',     icon: faDice, },
-	random:          { in: ['number'],                     out: 'boolean', category: 'random',     icon: faDice, },
-	randomPick:      { in: [0],                            out: 0,         category: 'random',     icon: faDice, },
 	dailyRannum:     { in: ['number', 'number'],           out: 'number',  category: 'random',     icon: faDice, },
+	random:          { in: ['number'],                     out: 'boolean', category: 'random',     icon: faDice, },
 	dailyRandom:     { in: ['number'],                     out: 'boolean', category: 'random',     icon: faDice, },
+	randomPick:      { in: [0],                            out: 0,         category: 'random',     icon: faDice, },
 	dailyRandomPick: { in: [0],                            out: 0,         category: 'random',     icon: faDice, },
 };
 
@@ -94,6 +97,7 @@ type PageVar = { name: string; value: any; type: Type; };
 
 const envVarsDef = {
 	AI: 'string',
+	URL: 'string',
 	VERSION: 'string',
 	LOGIN: 'boolean',
 	NAME: 'string',
@@ -117,7 +121,7 @@ export class AiScript {
 	public static blockDefs = blockDefs;
 	public static funcDefs = funcDefs;
 	private opts: {
-		randomSeed?: string; user?: any; visitor?: any;
+		randomSeed?: string; user?: any; visitor?: any; page?: any; url?: string;
 	};
 
 	constructor(variables: Variable[] = [], pageVars: PageVar[] = [], opts: AiScript['opts'] = {}) {
@@ -128,6 +132,7 @@ export class AiScript {
 		this.envVars = {
 			AI: 'kawaii',
 			VERSION: version,
+			URL: opts.page ? `${opts.url}/@${opts.page.user.username}/pages/${opts.page.name}` : '',
 			LOGIN: opts.visitor != null,
 			NAME: opts.visitor ? opts.visitor.name : '',
 			USERNAME: opts.visitor ? opts.visitor.username : '',
@@ -421,6 +426,8 @@ export class AiScript {
 			strPick: (a, b) => a[b - 1],
 			strReplace: (a, b, c) => a.split(b).join(c),
 			strReverse: (a) => a.split('').reverse().join(''),
+			stringToNumber: (a) => parseInt(a),
+			numberToString: (a) => a.toString(),
 			random: (probability) => Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * 100) < probability,
 			rannum: (min, max) => min + Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * (max - min + 1)),
 			randomPick: (list) => list[Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * list.length)],
diff --git a/src/client/app/common/scripts/collect-page-vars.ts b/src/client/app/common/scripts/collect-page-vars.ts
index 86687e21f4..92727ce6db 100644
--- a/src/client/app/common/scripts/collect-page-vars.ts
+++ b/src/client/app/common/scripts/collect-page-vars.ts
@@ -2,10 +2,22 @@ export function collectPageVars(content) {
 	const pageVars = [];
 	const collect = (xs: any[]) => {
 		for (const x of xs) {
-			if (x.type === 'input') {
+			if (x.type === 'textInput') {
 				pageVars.push({
 					name: x.name,
-					type: x.inputType,
+					type: 'string',
+					value: x.default
+				});
+			} else if (x.type === 'textareaInput') {
+				pageVars.push({
+					name: x.name,
+					type: 'string',
+					value: x.default
+				});
+			} else if (x.type === 'numberInput') {
+				pageVars.push({
+					name: x.name,
+					type: 'number',
 					value: x.default
 				});
 			} else if (x.type === 'switch') {
diff --git a/src/client/app/common/views/components/page-editor/page-editor.button.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.button.vue
similarity index 93%
rename from src/client/app/common/views/components/page-editor/page-editor.button.vue
rename to src/client/app/common/views/components/page-editor/els/page-editor.el.button.vue
index d5fc243818..3e2d3fe19d 100644
--- a/src/client/app/common/views/components/page-editor/page-editor.button.vue
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.button.vue
@@ -16,9 +16,9 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import i18n from '../../../../i18n';
 import { faBolt } from '@fortawesome/free-solid-svg-icons';
-import XContainer from './page-editor.container.vue';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
 
 export default Vue.extend({
 	i18n: i18n('pages'),
diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue
new file mode 100644
index 0000000000..87fc9e6faf
--- /dev/null
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.if.vue
@@ -0,0 +1,113 @@
+<template>
+<x-container @remove="() => $emit('remove')">
+	<template #header><fa :icon="faQuestion"/> {{ $t('blocks.if') }}</template>
+	<template #func>
+		<button @click="add()">
+			<fa :icon="faPlus"/>
+		</button>
+	</template>
+
+	<section class="romcojzs">
+		<ui-select v-model="value.var">
+			<template #label>{{ $t('blocks._if.variable') }}</template>
+			<option v-for="v in aiScript.getVarsByType('boolean')" :value="v.name">{{ v.name }}</option>
+			<optgroup :label="$t('script.pageVariables')">
+				<option v-for="v in aiScript.getPageVarsByType('boolean')" :value="v">{{ v }}</option>
+			</optgroup>
+			<optgroup :label="$t('script.enviromentVariables')">
+				<option v-for="v in aiScript.getEnvVarsByType('boolean')" :value="v">{{ v }}</option>
+			</optgroup>
+		</ui-select>
+
+		<div class="children">
+			<x-block v-for="child in value.children" :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id" :ai-script="aiScript"/>
+		</div>
+	</section>
+</x-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import * as uuid from 'uuid';
+import { faPlus, faQuestion } from '@fortawesome/free-solid-svg-icons';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
+
+export default Vue.extend({
+	i18n: i18n('pages'),
+
+	components: {
+		XContainer
+	},
+
+	inject: ['getPageBlockList'],
+
+	props: {
+		value: {
+			required: true
+		},
+		aiScript: {
+			required: true,
+		},
+	},
+
+	data() {
+		return {
+			faPlus, faQuestion
+		};
+	},
+
+	beforeCreate() {
+		this.$options.components.XBlock = require('../page-editor.block.vue').default
+	},
+
+	created() {
+		if (this.value.children == null) Vue.set(this.value, 'children', []);
+		if (this.value.var === undefined) Vue.set(this.value, 'var', null);
+	},
+
+	methods: {
+		async add() {
+			const { canceled, result: type } = await this.$root.dialog({
+				type: null,
+				title: this.$t('choose-block'),
+				select: {
+					groupedItems: this.getPageBlockList()
+				},
+				showCancelButton: true
+			});
+			if (canceled) return;
+
+			const id = uuid.v4();
+			this.value.children.push({ id, type });
+		},
+
+		updateItem(v) {
+			const i = this.value.children.findIndex(x => x.id === v.id);
+			const newValue = [
+				...this.value.children.slice(0, i),
+				v,
+				...this.value.children.slice(i + 1)
+			];
+			this.value.children = newValue;
+			this.$emit('input', this.value);
+		},
+
+		remove(el) {
+			const i = this.value.children.findIndex(x => x.id === el.id);
+			const newValue = [
+				...this.value.children.slice(0, i),
+				...this.value.children.slice(i + 1)
+			];
+			this.value.children = newValue;
+			this.$emit('input', this.value);
+		}
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+.romcojzs
+	padding 0 16px 16px 16px
+
+</style>
diff --git a/src/client/app/common/views/components/page-editor/page-editor.image.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.image.vue
similarity index 89%
rename from src/client/app/common/views/components/page-editor/page-editor.image.vue
rename to src/client/app/common/views/components/page-editor/els/page-editor.el.image.vue
index 0bc1816e8d..5ada8c77ba 100644
--- a/src/client/app/common/views/components/page-editor/page-editor.image.vue
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.image.vue
@@ -15,11 +15,11 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import i18n from '../../../../i18n';
 import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
 import { faImage, faFolderOpen } from '@fortawesome/free-regular-svg-icons';
-import XContainer from './page-editor.container.vue';
-import XFileThumbnail from '../drive-file-thumbnail.vue';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
+import XFileThumbnail from '../../drive-file-thumbnail.vue';
 
 export default Vue.extend({
 	i18n: i18n('pages'),
diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.number-input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.number-input.vue
new file mode 100644
index 0000000000..aff6cf6b6b
--- /dev/null
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.number-input.vue
@@ -0,0 +1,42 @@
+<template>
+<x-container @remove="() => $emit('remove')">
+	<template #header><fa :icon="faBolt"/> {{ $t('blocks.numberInput') }}</template>
+
+	<section style="padding: 0 16px 0 16px;">
+		<ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._numberInput.name') }}</span></ui-input>
+		<ui-input v-model="value.text"><span>{{ $t('blocks._numberInput.text') }}</span></ui-input>
+		<ui-input v-model="value.default" type="number"><span>{{ $t('blocks._numberInput.default') }}</span></ui-input>
+	</section>
+</x-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
+
+export default Vue.extend({
+	i18n: i18n('pages'),
+
+	components: {
+		XContainer
+	},
+
+	props: {
+		value: {
+			required: true
+		},
+	},
+
+	data() {
+		return {
+			faBolt, faSquareRootAlt
+		};
+	},
+
+	created() {
+		if (this.value.name == null) Vue.set(this.value, 'name', '');
+	},
+});
+</script>
diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.post.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.post.vue
new file mode 100644
index 0000000000..a01fc57f26
--- /dev/null
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.post.vue
@@ -0,0 +1,44 @@
+<template>
+<x-container @remove="() => $emit('remove')">
+	<template #header><fa :icon="faPaperPlane"/> {{ $t('blocks.post') }}</template>
+
+	<section style="padding: 0 16px 16px 16px;">
+		<ui-textarea v-model="value.text">{{ $t('blocks._post.text') }}</ui-textarea>
+	</section>
+</x-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faPaperPlane } from '@fortawesome/free-regular-svg-icons';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
+
+export default Vue.extend({
+	i18n: i18n('pages'),
+
+	components: {
+		XContainer
+	},
+
+	props: {
+		value: {
+			required: true
+		},
+	},
+
+	data() {
+		return {
+			faPaperPlane
+		};
+	},
+
+	beforeCreate() {
+		this.$options.components.XBlock = require('../page-editor.block.vue').default
+	},
+
+	created() {
+		if (this.value.text == null) Vue.set(this.value, 'text', '');
+	},
+});
+</script>
diff --git a/src/client/app/common/views/components/page-editor/page-editor.section.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue
similarity index 80%
rename from src/client/app/common/views/components/page-editor/page-editor.section.vue
rename to src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue
index d7a247b0b1..747de481a6 100644
--- a/src/client/app/common/views/components/page-editor/page-editor.section.vue
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.section.vue
@@ -12,7 +12,7 @@
 
 	<section class="ilrvjyvi">
 		<div class="children">
-			<x-block v-for="child in value.children" :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id"/>
+			<x-block v-for="child in value.children" :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id" :ai-script="aiScript"/>
 		</div>
 	</section>
 </x-container>
@@ -20,11 +20,11 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import i18n from '../../../../i18n';
+import * as uuid from 'uuid';
 import { faPlus, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
 import { faStickyNote } from '@fortawesome/free-regular-svg-icons';
-import XContainer from './page-editor.container.vue';
-import * as uuid from 'uuid';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
 
 export default Vue.extend({
 	i18n: i18n('pages'),
@@ -33,10 +33,15 @@ export default Vue.extend({
 		XContainer
 	},
 
+	inject: ['getPageBlockList'],
+
 	props: {
 		value: {
 			required: true
 		},
+		aiScript: {
+			required: true,
+		},
 	},
 
 	data() {
@@ -46,7 +51,7 @@ export default Vue.extend({
 	},
 
 	beforeCreate() {
-		this.$options.components.XBlock = require('./page-editor.block.vue').default
+		this.$options.components.XBlock = require('../page-editor.block.vue').default
 	},
 
 	created() {
@@ -79,19 +84,7 @@ export default Vue.extend({
 				type: null,
 				title: this.$t('choose-block'),
 				select: {
-					items: [{
-						value: 'section', text: this.$t('blocks.section')
-					}, {
-						value: 'text', text: this.$t('blocks.text')
-					}, {
-						value: 'image', text: this.$t('blocks.image')
-					}, {
-						value: 'button', text: this.$t('blocks.button')
-					}, {
-						value: 'input', text: this.$t('blocks.input')
-					}, {
-						value: 'switch', text: this.$t('blocks.switch')
-					}]
+					groupedItems: this.getPageBlockList()
 				},
 				showCancelButton: true
 			});
diff --git a/src/client/app/common/views/components/page-editor/page-editor.switch.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.switch.vue
similarity index 91%
rename from src/client/app/common/views/components/page-editor/page-editor.switch.vue
rename to src/client/app/common/views/components/page-editor/els/page-editor.el.switch.vue
index a9cfa2844f..3404404d99 100644
--- a/src/client/app/common/views/components/page-editor/page-editor.switch.vue
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.switch.vue
@@ -12,9 +12,9 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import i18n from '../../../../i18n';
 import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons';
-import XContainer from './page-editor.container.vue';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
 
 export default Vue.extend({
 	i18n: i18n('pages'),
diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.text-input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.text-input.vue
new file mode 100644
index 0000000000..6c4783fd7e
--- /dev/null
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.text-input.vue
@@ -0,0 +1,42 @@
+<template>
+<x-container @remove="() => $emit('remove')">
+	<template #header><fa :icon="faBolt"/> {{ $t('blocks.textInput') }}</template>
+
+	<section style="padding: 0 16px 0 16px;">
+		<ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._textInput.name') }}</span></ui-input>
+		<ui-input v-model="value.text"><span>{{ $t('blocks._textInput.text') }}</span></ui-input>
+		<ui-input v-model="value.default" type="text"><span>{{ $t('blocks._textInput.default') }}</span></ui-input>
+	</section>
+</x-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
+
+export default Vue.extend({
+	i18n: i18n('pages'),
+
+	components: {
+		XContainer
+	},
+
+	props: {
+		value: {
+			required: true
+		},
+	},
+
+	data() {
+		return {
+			faBolt, faSquareRootAlt
+		};
+	},
+
+	created() {
+		if (this.value.name == null) Vue.set(this.value, 'name', '');
+	},
+});
+</script>
diff --git a/src/client/app/common/views/components/page-editor/page-editor.text.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.text.vue
similarity index 89%
rename from src/client/app/common/views/components/page-editor/page-editor.text.vue
rename to src/client/app/common/views/components/page-editor/els/page-editor.el.text.vue
index 7368931b2f..1d07c9157a 100644
--- a/src/client/app/common/views/components/page-editor/page-editor.text.vue
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.text.vue
@@ -10,9 +10,9 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import i18n from '../../../../i18n';
 import { faAlignLeft } from '@fortawesome/free-solid-svg-icons';
-import XContainer from './page-editor.container.vue';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
 
 export default Vue.extend({
 	i18n: i18n('pages'),
@@ -54,4 +54,5 @@ export default Vue.extend({
 		padding 16px
 		background transparent
 		color var(--text)
+		font-size 14px
 </style>
diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea-input.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea-input.vue
new file mode 100644
index 0000000000..68edf13824
--- /dev/null
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea-input.vue
@@ -0,0 +1,42 @@
+<template>
+<x-container @remove="() => $emit('remove')">
+	<template #header><fa :icon="faBolt"/> {{ $t('blocks.textareaInput') }}</template>
+
+	<section style="padding: 0 16px 16px 16px;">
+		<ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._textareaInput.name') }}</span></ui-input>
+		<ui-input v-model="value.text"><span>{{ $t('blocks._textareaInput.text') }}</span></ui-input>
+		<ui-textarea v-model="value.default"><span>{{ $t('blocks._textareaInput.default') }}</span></ui-textarea>
+	</section>
+</x-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
+
+export default Vue.extend({
+	i18n: i18n('pages'),
+
+	components: {
+		XContainer
+	},
+
+	props: {
+		value: {
+			required: true
+		},
+	},
+
+	data() {
+		return {
+			faBolt, faSquareRootAlt
+		};
+	},
+
+	created() {
+		if (this.value.name == null) Vue.set(this.value, 'name', '');
+	},
+});
+</script>
diff --git a/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea.vue b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea.vue
new file mode 100644
index 0000000000..4fbe497960
--- /dev/null
+++ b/src/client/app/common/views/components/page-editor/els/page-editor.el.textarea.vue
@@ -0,0 +1,58 @@
+<template>
+<x-container @remove="() => $emit('remove')">
+	<template #header><fa :icon="faAlignLeft"/> {{ $t('blocks.textarea') }}</template>
+
+	<section class="ihymsbbe">
+		<textarea v-model="value.text"></textarea>
+	</section>
+</x-container>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faAlignLeft } from '@fortawesome/free-solid-svg-icons';
+import i18n from '../../../../../i18n';
+import XContainer from '../page-editor.container.vue';
+
+export default Vue.extend({
+	i18n: i18n('pages'),
+
+	components: {
+		XContainer
+	},
+
+	props: {
+		value: {
+			required: true
+		},
+	},
+
+	data() {
+		return {
+			faAlignLeft,
+		};
+	},
+
+	created() {
+		if (this.value.text == null) Vue.set(this.value, 'text', '');
+	},
+});
+</script>
+
+<style lang="stylus" scoped>
+.ihymsbbe
+	> textarea
+		display block
+		-webkit-appearance none
+		-moz-appearance none
+		appearance none
+		width 100%
+		min-width 100%
+		min-height 150px
+		border none
+		box-shadow none
+		padding 16px
+		background transparent
+		color var(--text)
+		font-size 14px
+</style>
diff --git a/src/client/app/common/views/components/page-editor/page-editor.block.vue b/src/client/app/common/views/components/page-editor/page-editor.block.vue
index a3e1488d1b..7d4505fca8 100644
--- a/src/client/app/common/views/components/page-editor/page-editor.block.vue
+++ b/src/client/app/common/views/components/page-editor/page-editor.block.vue
@@ -1,25 +1,33 @@
 <template>
-<component :is="'x-' + value.type" :value="value" @input="v => updateItem(v)" @remove="() => $emit('remove', value)" :key="value.id"/>
+<component :is="'x-' + value.type" :value="value" @input="v => updateItem(v)" @remove="() => $emit('remove', value)" :key="value.id" :ai-script="aiScript"/>
 </template>
 
 <script lang="ts">
 import Vue from 'vue';
-import XSection from './page-editor.section.vue';
-import XText from './page-editor.text.vue';
-import XImage from './page-editor.image.vue';
-import XButton from './page-editor.button.vue';
-import XInput from './page-editor.input.vue';
-import XSwitch from './page-editor.switch.vue';
+import XSection from './els/page-editor.el.section.vue';
+import XText from './els/page-editor.el.text.vue';
+import XTextarea from './els/page-editor.el.textarea.vue';
+import XImage from './els/page-editor.el.image.vue';
+import XButton from './els/page-editor.el.button.vue';
+import XTextInput from './els/page-editor.el.text-input.vue';
+import XTextareaInput from './els/page-editor.el.textarea-input.vue';
+import XNumberInput from './els/page-editor.el.text-input.vue';
+import XSwitch from './els/page-editor.el.switch.vue';
+import XIf from './els/page-editor.el.if.vue';
+import XPost from './els/page-editor.el.post.vue';
 
 export default Vue.extend({
 	components: {
-		XSection, XText, XImage, XButton, XInput, XSwitch
+		XSection, XText, XImage, XButton, XTextarea, XTextInput, XTextareaInput, XNumberInput, XSwitch, XIf, XPost
 	},
 
 	props: {
 		value: {
 			required: true
-		}
+		},
+		aiScript: {
+			required: true,
+		},
 	},
 });
 </script>
diff --git a/src/client/app/common/views/components/page-editor/page-editor.input.vue b/src/client/app/common/views/components/page-editor/page-editor.input.vue
deleted file mode 100644
index 4e13840439..0000000000
--- a/src/client/app/common/views/components/page-editor/page-editor.input.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<template>
-<x-container @remove="() => $emit('remove')">
-	<template #header><fa :icon="faBolt"/> {{ $t('blocks.input') }}</template>
-
-	<section class="dnvasjon">
-		<ui-input v-model="value.name"><template #prefix><fa :icon="faSquareRootAlt"/></template><span>{{ $t('blocks._input.name') }}</span></ui-input>
-		<ui-input v-model="value.text"><span>{{ $t('blocks._input.text') }}</span></ui-input>
-		<ui-select v-model="value.inputType">
-			<template #label>{{ $t('blocks._input.inputType') }}</template>
-			<option value="string">{{ $t('blocks._input._inputType.string') }}</option>
-			<option value="number">{{ $t('blocks._input._inputType.number') }}</option>
-		</ui-select>
-		<ui-input v-model="value.default" :type="value.inputType"><span>{{ $t('blocks._input.default') }}</span></ui-input>
-	</section>
-</x-container>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import i18n from '../../../../i18n';
-import { faBolt, faSquareRootAlt } from '@fortawesome/free-solid-svg-icons';
-import XContainer from './page-editor.container.vue';
-
-export default Vue.extend({
-	i18n: i18n('pages'),
-
-	components: {
-		XContainer
-	},
-
-	props: {
-		value: {
-			required: true
-		},
-	},
-
-	data() {
-		return {
-			faBolt, faSquareRootAlt
-		};
-	},
-
-	created() {
-		if (this.value.name == null) Vue.set(this.value, 'name', '');
-		if (this.value.inputType == null) Vue.set(this.value, 'inputType', 'string');
-
-		this.$watch('value.inputType', t => {
-			if (this.value.default != null) {
-				if (t === 'number') this.value.default = parseInt(this.value.default, 10);
-				if (t === 'string') this.value.default = this.value.default.toString();
-			}
-		});
-	},
-});
-</script>
-
-<style lang="stylus" scoped>
-.dnvasjon
-	padding 0 16px 0 16px
-
-</style>
diff --git a/src/client/app/common/views/components/page-editor/page-editor.vue b/src/client/app/common/views/components/page-editor/page-editor.vue
index 8b25828515..f8959fb0f1 100644
--- a/src/client/app/common/views/components/page-editor/page-editor.vue
+++ b/src/client/app/common/views/components/page-editor/page-editor.vue
@@ -2,16 +2,16 @@
 <div>
 	<div class="gwbmwxkm" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners }">
 		<header>
-			<div class="title"><fa :icon="faStickyNote"/> {{ pageId ? $t('edit-page') : $t('new-page') }}</div>
+			<div class="title"><fa :icon="faStickyNote"/> {{ readonly ? $t('read-page') : pageId ? $t('edit-page') : $t('new-page') }}</div>
 			<div class="buttons">
-				<button @click="del()"><fa :icon="faTrashAlt"/></button>
+				<button @click="del()" v-if="!readonly"><fa :icon="faTrashAlt"/></button>
 				<button @click="() => showOptions = !showOptions"><fa :icon="faCog"/></button>
-				<button @click="save()"><fa :icon="faSave"/></button>
+				<button @click="save()" v-if="!readonly"><fa :icon="faSave"/></button>
 			</div>
 		</header>
 
 		<section>
-			<a class="view" v-if="pageId" :href="`/@${ $store.state.i.username }/pages/${ currentName }`" target="_blank"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('view-page') }}</a>
+			<a class="view" v-if="pageId" :href="`/@${ author.username }/pages/${ currentName }`" target="_blank"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('view-page') }}</a>
 
 			<ui-input v-model="title">
 				<span>{{ $t('title') }}</span>
@@ -23,7 +23,7 @@
 				</ui-input>
 
 				<ui-input v-model="name">
-					<template #prefix>{{ url }}/@{{ $store.state.i.username }}/pages/</template>
+					<template #prefix>{{ url }}/@{{ author.username }}/pages/</template>
 					<span>{{ $t('url') }}</span>
 				</ui-input>
 
@@ -45,10 +45,10 @@
 			</template>
 
 			<div class="content" v-for="child in content">
-				<x-block :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id"/>
+				<x-block :value="child" @input="v => updateItem(v)" @remove="() => remove(child)" :key="child.id" :ai-script="aiScript"/>
 			</div>
 
-			<ui-button @click="add()"><fa :icon="faPlus"/></ui-button>
+			<ui-button @click="add()" v-if="!readonly"><fa :icon="faPlus"/></ui-button>
 		</section>
 	</div>
 
@@ -70,7 +70,7 @@
 				</template>
 			</div>
 
-			<ui-button @click="addVariable()" class="add"><fa :icon="faPlus"/></ui-button>
+			<ui-button @click="addVariable()" class="add" v-if="!readonly"><fa :icon="faPlus"/></ui-button>
 
 			<ui-info><span v-html="$t('variables-info')"></span><a @click="() => moreDetails = true" style="display:block;">{{ $t('more-details') }}</a></ui-info>
 
@@ -106,11 +106,17 @@ export default Vue.extend({
 		page: {
 			type: String,
 			required: false
-		}
+		},
+		readonly: {
+			type: Boolean,
+			required: false,
+			default: false
+		},
 	},
 
 	data() {
 		return {
+			author: this.$store.state.i,
 			pageId: null,
 			currentName: null,
 			title: '',
@@ -157,6 +163,7 @@ export default Vue.extend({
 			this.$root.api('pages/show', {
 				pageId: this.page,
 			}).then(page => {
+				this.author = page.user;
 				this.pageId = page.id;
 				this.title = page.title;
 				this.name = page.name;
@@ -180,7 +187,9 @@ export default Vue.extend({
 
 	provide() {
 		return {
-			getScriptBlockList: this.getScriptBlockList
+			readonly: this.readonly,
+			getScriptBlockList: this.getScriptBlockList,
+			getPageBlockList: this.getPageBlockList
 		}
 	},
 
@@ -250,19 +259,7 @@ export default Vue.extend({
 				type: null,
 				title: this.$t('choose-block'),
 				select: {
-					items: [{
-						value: 'section', text: this.$t('blocks.section')
-					}, {
-						value: 'text', text: this.$t('blocks.text')
-					}, {
-						value: 'image', text: this.$t('blocks.image')
-					}, {
-						value: 'button', text: this.$t('blocks.button')
-					}, {
-						value: 'input', text: this.$t('blocks.input')
-					}, {
-						value: 'switch', text: this.$t('blocks.switch')
-					}]
+					groupedItems: this.getPageBlockList()
 				},
 				showCancelButton: true
 			});
@@ -324,6 +321,33 @@ export default Vue.extend({
 			this.variables = newValue;
 		},
 
+		getPageBlockList() {
+			return [{
+				label: this.$t('content-blocks'),
+				items: [
+					{ value: 'section', text: this.$t('blocks.section') },
+					{ value: 'text', text: this.$t('blocks.text') },
+					{ value: 'image', text: this.$t('blocks.image') },
+					{ value: 'textarea', text: this.$t('blocks.textarea') },
+				]
+			}, {
+				label: this.$t('input-blocks'),
+				items: [
+					{ value: 'button', text: this.$t('blocks.button') },
+					{ value: 'textInput', text: this.$t('blocks.textInput') },
+					{ value: 'textareaInput', text: this.$t('blocks.textareaInput') },
+					{ value: 'numberInput', text: this.$t('blocks.numberInput') },
+					{ value: 'switch', text: this.$t('blocks.switch') }
+				]
+			}, {
+				label: this.$t('special-blocks'),
+				items: [
+					{ value: 'if', text: this.$t('blocks.if') },
+					{ value: 'post', text: this.$t('blocks.post') }
+				]
+			}];
+		},
+
 		getScriptBlockList(type: string = null) {
 			const list = [];
 
@@ -436,6 +460,7 @@ export default Vue.extend({
 		> .view
 			display inline-block
 			margin 16px 0 0 0
+			font-size 14px
 
 		> .content
 			margin-bottom 16px
diff --git a/src/client/app/common/views/pages/page/page.block.vue b/src/client/app/common/views/pages/page/page.block.vue
index 48a89f9de7..f348107cc7 100644
--- a/src/client/app/common/views/pages/page/page.block.vue
+++ b/src/client/app/common/views/pages/page/page.block.vue
@@ -8,12 +8,17 @@ import XText from './page.text.vue';
 import XSection from './page.section.vue';
 import XImage from './page.image.vue';
 import XButton from './page.button.vue';
-import XInput from './page.input.vue';
+import XNumberInput from './page.number-input.vue';
+import XTextInput from './page.text-input.vue';
+import XTextareaInput from './page.textarea-input.vue';
 import XSwitch from './page.switch.vue';
+import XIf from './page.if.vue';
+import XTextarea from './page.textarea.vue';
+import XPost from './page.post.vue';
 
 export default Vue.extend({
 	components: {
-		XText, XSection, XImage, XButton, XInput, XSwitch
+		XText, XSection, XImage, XButton, XNumberInput, XTextInput, XTextareaInput, XTextarea, XPost, XSwitch, XIf
 	},
 
 	props: {
diff --git a/src/client/app/common/views/pages/page/page.button.vue b/src/client/app/common/views/pages/page/page.button.vue
index 5063d27122..b77d856d5d 100644
--- a/src/client/app/common/views/pages/page/page.button.vue
+++ b/src/client/app/common/views/pages/page/page.button.vue
@@ -1,6 +1,6 @@
 <template>
 <div>
-	<ui-button class="kudkigyw" @click="click()">{{ value.text }}</ui-button>
+	<ui-button class="kudkigyw" @click="click()">{{ script.interpolate(value.text) }}</ui-button>
 </div>
 </template>
 
diff --git a/src/client/app/common/views/pages/page/page.if.vue b/src/client/app/common/views/pages/page/page.if.vue
new file mode 100644
index 0000000000..9dbeaf64fb
--- /dev/null
+++ b/src/client/app/common/views/pages/page/page.if.vue
@@ -0,0 +1,30 @@
+<template>
+<div v-show="script.vars.find(x => x.name === value.var).value">
+	<x-block v-for="child in value.children" :value="child" :page="page" :script="script" :key="child.id" :h="h"/>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+
+export default Vue.extend({
+	props: {
+		value: {
+			required: true
+		},
+		script: {
+			required: true
+		},
+		page: {
+			required: true
+		},
+		h: {
+			required: true
+		}
+	},
+
+	beforeCreate() {
+		this.$options.components.XBlock = require('./page.block.vue').default
+	},
+});
+</script>
diff --git a/src/client/app/common/views/pages/page/page.input.vue b/src/client/app/common/views/pages/page/page.number-input.vue
similarity index 64%
rename from src/client/app/common/views/pages/page/page.input.vue
rename to src/client/app/common/views/pages/page/page.number-input.vue
index cda5550337..51d538c369 100644
--- a/src/client/app/common/views/pages/page/page.input.vue
+++ b/src/client/app/common/views/pages/page/page.number-input.vue
@@ -1,6 +1,6 @@
 <template>
 <div>
-	<ui-input class="kudkigyw" v-model="v" :type="value.inputType">{{ value.text }}</ui-input>
+	<ui-input class="kudkigyw" v-model="v" type="number">{{ script.interpolate(value.text) }}</ui-input>
 </div>
 </template>
 
@@ -25,9 +25,7 @@ export default Vue.extend({
 
 	watch: {
 		v() {
-			let v = this.v;
-			if (this.value.inputType === 'number') v = parseInt(v, 10);
-			this.script.aiScript.updatePageVar(this.value.name, v);
+			this.script.aiScript.updatePageVar(this.value.name, this.v);
 			this.script.reEval();
 		}
 	}
diff --git a/src/client/app/common/views/pages/page/page.post.vue b/src/client/app/common/views/pages/page/page.post.vue
new file mode 100644
index 0000000000..cb695e21e9
--- /dev/null
+++ b/src/client/app/common/views/pages/page/page.post.vue
@@ -0,0 +1,68 @@
+<template>
+<div class="ngbfujlo">
+	<ui-textarea class="textarea" :value="text" readonly></ui-textarea>
+	<ui-button primary @click="post()" :disabled="posting || posted">{{ posted ? $t('posted-from-post-form') : $t('post-from-post-form') }}</ui-button>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import i18n from '../../../../i18n';
+
+export default Vue.extend({
+	i18n: i18n('pages'),
+
+	props: {
+		value: {
+			required: true
+		},
+		script: {
+			required: true
+		}
+	},
+
+	data() {
+		return {
+			text: this.script.interpolate(this.value.text),
+			posted: false,
+			posting: false,
+		};
+	},
+
+	created() {
+		this.$watch('script.vars', () => {
+			this.text = this.script.interpolate(this.value.text);
+		}, { deep: true });
+	},
+
+	methods: {
+		post() {
+			this.posting = true;
+			this.$root.api('notes/create', {
+				text: this.text,
+			}).then(() => {
+				this.posted = true;
+				this.$root.dialog({
+					type: 'success',
+					splash: true
+				});
+			});
+		}
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+.ngbfujlo
+	padding 0 32px 32px 32px
+	border solid 2px var(--pageBlockBorder)
+	border-radius 6px
+
+	@media (max-width 600px)
+		padding 0 16px 16px 16px
+
+		> .textarea
+			margin-top 16px
+			margin-bottom 16px
+
+</style>
diff --git a/src/client/app/common/views/pages/page/page.switch.vue b/src/client/app/common/views/pages/page/page.switch.vue
index 962ab84bb5..a401e5dfbf 100644
--- a/src/client/app/common/views/pages/page/page.switch.vue
+++ b/src/client/app/common/views/pages/page/page.switch.vue
@@ -1,6 +1,6 @@
 <template>
 <div class="hkcxmtwj">
-	<ui-switch v-model="v">{{ value.text }}</ui-switch>
+	<ui-switch v-model="v">{{ script.interpolate(value.text) }}</ui-switch>
 </div>
 </template>
 
@@ -36,4 +36,8 @@ export default Vue.extend({
 .hkcxmtwj
 	display inline-block
 	margin 16px auto
+
+	& + .hkcxmtwj
+		margin-left 16px
+
 </style>
diff --git a/src/client/app/common/views/pages/page/page.text-input.vue b/src/client/app/common/views/pages/page/page.text-input.vue
new file mode 100644
index 0000000000..3d659edd5e
--- /dev/null
+++ b/src/client/app/common/views/pages/page/page.text-input.vue
@@ -0,0 +1,41 @@
+<template>
+<div>
+	<ui-input class="kudkigyw" v-model="v" type="text">{{ script.interpolate(value.text) }}</ui-input>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+
+export default Vue.extend({
+	props: {
+		value: {
+			required: true
+		},
+		script: {
+			required: true
+		}
+	},
+
+	data() {
+		return {
+			v: this.value.default,
+		};
+	},
+
+	watch: {
+		v() {
+			this.script.aiScript.updatePageVar(this.value.name, this.v);
+			this.script.reEval();
+		}
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+.kudkigyw
+	display inline-block
+	min-width 300px
+	max-width 450px
+	margin 8px 0
+</style>
diff --git a/src/client/app/common/views/pages/page/page.textarea-input.vue b/src/client/app/common/views/pages/page/page.textarea-input.vue
new file mode 100644
index 0000000000..fd8174c273
--- /dev/null
+++ b/src/client/app/common/views/pages/page/page.textarea-input.vue
@@ -0,0 +1,36 @@
+<template>
+<div>
+	<ui-textarea class="" v-model="v">{{ script.interpolate(value.text) }}</ui-textarea>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+
+export default Vue.extend({
+	props: {
+		value: {
+			required: true
+		},
+		script: {
+			required: true
+		}
+	},
+
+	data() {
+		return {
+			v: this.value.default,
+		};
+	},
+
+	watch: {
+		v() {
+			this.script.aiScript.updatePageVar(this.value.name, this.v);
+			this.script.reEval();
+		}
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+</style>
diff --git a/src/client/app/common/views/pages/page/page.textarea.vue b/src/client/app/common/views/pages/page/page.textarea.vue
new file mode 100644
index 0000000000..03c8542cb0
--- /dev/null
+++ b/src/client/app/common/views/pages/page/page.textarea.vue
@@ -0,0 +1,33 @@
+<template>
+<ui-textarea class="" :value="text" readonly></ui-textarea>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+
+export default Vue.extend({
+	props: {
+		value: {
+			required: true
+		},
+		script: {
+			required: true
+		}
+	},
+
+	data() {
+		return {
+			text: this.script.interpolate(this.value.text),
+		};
+	},
+
+	created() {
+		this.$watch('script.vars', () => {
+			this.text = this.script.interpolate(this.value.text);
+		}, { deep: true });
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+</style>
diff --git a/src/client/app/common/views/pages/page/page.vue b/src/client/app/common/views/pages/page/page.vue
index e7e8f76d53..88598d3527 100644
--- a/src/client/app/common/views/pages/page/page.vue
+++ b/src/client/app/common/views/pages/page/page.vue
@@ -23,6 +23,7 @@ import { faSave, faStickyNote } from '@fortawesome/free-regular-svg-icons';
 import XBlock from './page.block.vue';
 import { AiScript } from '../../../scripts/aiscript';
 import { collectPageVars } from '../../../scripts/collect-page-vars';
+import { url } from '../../../../config';
 
 class Script {
 	public aiScript: AiScript;
@@ -38,6 +39,7 @@ class Script {
 	}
 
 	public interpolate(str: string) {
+		if (str == null) return null;
 		return str.replace(/\{(.+?)\}/g, match => {
 			const v = this.vars.find(x => x.name === match.slice(1, -1).trim()).value;
 			return v == null ? 'NULL' : v.toString();
@@ -81,7 +83,9 @@ export default Vue.extend({
 			this.script = new Script(new AiScript(this.page.variables, pageVars, {
 				randomSeed: Math.random(),
 				user: page.user,
-				visitor: this.$store.state.i
+				visitor: this.$store.state.i,
+				page: page,
+				url: url
 			}));
 		});
 	},
diff --git a/src/client/app/mobile/views/pages/page.vue b/src/client/app/mobile/views/pages/page.vue
index 27ade4a398..f494abffd7 100644
--- a/src/client/app/mobile/views/pages/page.vue
+++ b/src/client/app/mobile/views/pages/page.vue
@@ -33,4 +33,7 @@ main
 	padding 16px
 	max-width 1000px
 
+	@media (min-width 600px)
+		padding 32px
+
 </style>
diff --git a/src/models/entities/instance.ts b/src/models/entities/instance.ts
index 977054263c..52c5215f14 100644
--- a/src/models/entities/instance.ts
+++ b/src/models/entities/instance.ts
@@ -71,7 +71,7 @@ export class Instance {
 	/**
 	 * ドライブ使用量
 	 */
-	@Column('integer', {
+	@Column('bigint', {
 		default: 0,
 	})
 	public driveUsage: number;
diff --git a/src/models/repositories/page.ts b/src/models/repositories/page.ts
index 4c1b4cc793..cbe385568e 100644
--- a/src/models/repositories/page.ts
+++ b/src/models/repositories/page.ts
@@ -27,6 +27,33 @@ export class PageRepository extends Repository<Page> {
 			}
 		};
 		collectFile(src.content);
+
+		// 後方互換性のため
+		let migrated = false;
+		const migrate = (xs: any[]) => {
+			for (const x of xs) {
+				if (x.type === 'input') {
+					if (x.inputType === 'text') {
+						x.type = 'textInput';
+					}
+					if (x.inputType === 'number') {
+						x.type = 'numberInput';
+						if (x.default) x.default = parseInt(x.default, 10);
+					}
+					migrated = true;
+				}
+				if (x.children) {
+					migrate(x.children);
+				}
+			}
+		};
+		migrate(src.content);
+		if (migrated) {
+			this.update(src.id, {
+				content: src.content
+			});
+		}
+
 		return await awaitAll({
 			id: src.id,
 			createdAt: src.createdAt.toISOString(),
diff --git a/src/server/web/views/base.pug b/src/server/web/views/base.pug
index e61d29685a..733a306d56 100644
--- a/src/server/web/views/base.pug
+++ b/src/server/web/views/base.pug
@@ -11,7 +11,7 @@ html
 		meta(name='application-name' content='Misskey')
 		meta(name='referrer' content='origin')
 		meta(name='theme-color' content='#105779')
-		meta(property='og:site_name' content= title || 'Misskey')
+		meta(property='og:site_name' content= instanceName || 'Misskey')
 		link(rel='icon' href= icon || '/favicon.ico')
 		link(rel='manifest' href='/manifest.json')