diff --git a/extensions/gitpod-shared/package.json b/extensions/gitpod-shared/package.json
index a3d799c9d2f2c..45a44daa71b18 100644
--- a/extensions/gitpod-shared/package.json
+++ b/extensions/gitpod-shared/package.json
@@ -12,6 +12,7 @@
     "prepare": "node scripts/inflate.js"
   },
   "devDependencies": {
+    "@types/js-yaml": "^4.0.5",
     "@types/node": "16.x",
     "@types/uuid": "^8.3.1",
     "@types/ws": "^7.2.6"
@@ -20,8 +21,9 @@
     "@gitpod/gitpod-protocol": "main",
     "@gitpod/supervisor-api-grpc": "main",
     "bufferutil": "^4.0.1",
-    "utf-8-validate": "^5.0.2",
+    "js-yaml": "^4.1.0",
     "reconnecting-websocket": "^4.4.0",
+    "utf-8-validate": "^5.0.2",
     "uuid": "^8.3.1",
     "vscode-nls": "^5.0.0",
     "ws": "^7.4.6",
diff --git a/extensions/gitpod-shared/scripts/inflate.js b/extensions/gitpod-shared/scripts/inflate.js
index 8e9d1704c80e3..134376ca8a9ed 100644
--- a/extensions/gitpod-shared/scripts/inflate.js
+++ b/extensions/gitpod-shared/scripts/inflate.js
@@ -12,6 +12,7 @@ const nls = {
 	'openSettings': 'Gitpod: Open Settings',
 	'openContext': 'Gitpod: Open Context',
 	'openDocumentation': 'Gitpod: Documentation',
+	'showReleaseNotes': 'Gitpod: Show Release Notes',
 	'openDiscord': 'Gitpod: Open Community Chat',
 	'openTwitter': 'Gitpod: Follow us on Twitter',
 	'reportIssue': 'Gitpod: Report Issue',
@@ -72,6 +73,11 @@ const commands = [
 		'title': '%reportIssue%',
 		'enablement': 'gitpod.inWorkspace == true'
 	},
+	{
+		'command': 'gitpod.showReleaseNotes',
+		'title': '%showReleaseNotes%',
+		'enablement': 'gitpod.inWorkspace == true'
+	},
 	{
 		'command': 'gitpod.upgradeSubscription',
 		'title': '%upgradeSubscription%',
@@ -160,6 +166,11 @@ const remoteMenus = [
 		'group': 'remote_00_gitpod_navigation@90',
 		'when': 'gitpod.inWorkspace == true'
 	},
+	{
+		'command': 'gitpod.showReleaseNotes',
+		'group': 'remote_00_gitpod_navigation@70',
+		'when': 'gitpod.inWorkspace == true'
+	},
 	{
 		'command': 'gitpod.upgradeSubscription',
 		'group': 'remote_00_gitpod_navigation@100',
diff --git a/extensions/gitpod-shared/src/common/cache.ts b/extensions/gitpod-shared/src/common/cache.ts
new file mode 100644
index 0000000000000..8b17a8b8e8eec
--- /dev/null
+++ b/extensions/gitpod-shared/src/common/cache.ts
@@ -0,0 +1,52 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Gitpod. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as vscode from 'vscode';
+
+const CACHE_KEY = 'gitpod.cache';
+
+interface CacheObject {
+	value: any;
+	expiration?: number;
+}
+
+interface CacheMap { [key: string]: CacheObject }
+
+export class CacheHelper {
+	constructor(private readonly context: vscode.ExtensionContext) { }
+
+	set(key: string, value: any, expiration?: number) {
+		let obj = this.context.globalState.get<CacheMap>(CACHE_KEY);
+		if (!obj) {
+			obj = {};
+		}
+		const exp = expiration ? ((+ new Date()) / 1000 + expiration) : undefined;
+		obj[key] = { value, expiration: exp };
+		return this.context.globalState.update(CACHE_KEY, obj);
+	}
+
+	get(key: string) {
+		const value = this.context.globalState.get<CacheMap>(CACHE_KEY);
+		if (!value || !value[key]) {
+			return undefined;
+		}
+		const data = value[key];
+		if (!data.expiration) {
+			return data.value;
+		}
+		const now = (+ new Date()) / 1000;
+		return now > data.expiration ? undefined : data.value;
+	}
+
+	async handy<T>(key: string, cb: () => Thenable<{ value: T; ttl?: number }>) {
+		let d = this.get(key);
+		if (d === undefined) {
+			const tmp = await cb();
+			await this.set(key, tmp.value, tmp.ttl);
+			d = tmp.value;
+		}
+		return d as T;
+	}
+}
diff --git a/extensions/gitpod-shared/src/extension.ts b/extensions/gitpod-shared/src/extension.ts
index 27b3064d24cfd..1d2654cdf718c 100644
--- a/extensions/gitpod-shared/src/extension.ts
+++ b/extensions/gitpod-shared/src/extension.ts
@@ -6,6 +6,7 @@ import * as vscode from 'vscode';
 import { registerActiveLanguageAnalytics, registerUsageAnalytics } from './analytics';
 import { createGitpodExtensionContext, GitpodExtensionContext, registerDefaultLayout, registerNotifications, registerWorkspaceCommands, registerWorkspaceSharing, registerWorkspaceTimeout } from './features';
 
+export { registerReleaseNotesView } from './releaseNote';
 export { GitpodExtensionContext, registerTasks, SupervisorConnection, registerIpcHookCli } from './features';
 export * from './gitpod-plugin-model';
 
diff --git a/extensions/gitpod-shared/src/releaseNote.ts b/extensions/gitpod-shared/src/releaseNote.ts
new file mode 100644
index 0000000000000..51504c54c3d17
--- /dev/null
+++ b/extensions/gitpod-shared/src/releaseNote.ts
@@ -0,0 +1,347 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Gitpod. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import fetch, { Response } from 'node-fetch';
+import * as vscode from 'vscode';
+import { load } from 'js-yaml';
+import { CacheHelper } from './common/cache';
+
+const LAST_READ_RELEASE_NOTES_ID = 'gitpod.lastReadReleaseNotesId';
+
+export function registerReleaseNotesView(context: vscode.ExtensionContext) {
+	const cacheHelper = new CacheHelper(context);
+
+	async function shouldShowReleaseNotes(lastReadId: string | undefined) {
+		const releaseId = await getLastPublish(cacheHelper);
+		console.log(`gitpod release notes lastReadId: ${lastReadId}, latestReleaseId: ${releaseId}`);
+		return releaseId !== lastReadId;
+	}
+
+	context.subscriptions.push(
+		vscode.commands.registerCommand('gitpod.showReleaseNotes', () => {
+			ReleaseNotesPanel.createOrShow(context, cacheHelper);
+		})
+	);
+
+	// sync between machines
+	context.globalState.setKeysForSync([LAST_READ_RELEASE_NOTES_ID]);
+
+	const lastReadId = context.globalState.get<string>(LAST_READ_RELEASE_NOTES_ID);
+	shouldShowReleaseNotes(lastReadId).then(shouldShow => {
+		if (shouldShow) {
+			ReleaseNotesPanel.createOrShow(context, cacheHelper);
+		}
+	});
+}
+
+function getResponseCacheTime(resp: Response) {
+	const v = resp.headers.get('Cache-Control');
+	if (!v) {
+		return undefined;
+	}
+	const t = /max-age=(\d+)/.exec(v);
+	if (!t) {
+		return undefined;
+	}
+	return Number(t[1]);
+}
+
+async function getLastPublish(cacheHelper: CacheHelper) {
+	const url = `${websiteHost}/changelog/latest`;
+	return cacheHelper.handy(url, async () => {
+		const resp = await fetch(url);
+		if (!resp.ok) {
+			throw new Error(`Getting latest releaseId failed: ${resp.statusText}`);
+		}
+		const { releaseId } = JSON.parse(await resp.text());
+		return {
+			value: releaseId as string,
+			ttl: getResponseCacheTime(resp),
+		};
+	});
+
+}
+
+const websiteHost = 'https://www.gitpod.io';
+
+class ReleaseNotesPanel {
+	public static currentPanel: ReleaseNotesPanel | undefined;
+	public static readonly viewType = 'gitpodReleaseNotes';
+	private readonly panel: vscode.WebviewPanel;
+	private lastReadId: string | undefined;
+	private _disposables: vscode.Disposable[] = [];
+
+	private async loadChangelog(releaseId: string) {
+		const url = `${websiteHost}/changelog/raw-markdown?releaseId=${releaseId}`;
+		const md = await this.cacheHelper.handy(url, async () => {
+			const resp = await fetch(url);
+			if (!resp.ok) {
+				throw new Error(`Getting raw markdown content failed: ${resp.statusText}`);
+			}
+			const md = await resp.text();
+			return {
+				value: md,
+				ttl: getResponseCacheTime(resp),
+			};
+		});
+
+		const parseInfo = (md: string) => {
+			if (!md.startsWith('---')) {
+				return;
+			}
+			const lines = md.split('\n');
+			const end = lines.indexOf('---', 1);
+			const content = lines.slice(1, end).join('\n');
+			return load(content) as { title: string; date: string; image: string; alt: string; excerpt: string };
+		};
+		const info = parseInfo(md);
+
+		const content = md
+			.replace(/---.*?---/gms, '')
+			.replace(/<script>.*?<\/script>/gms, '')
+			.replace(/<Badge.*?text="(.*?)".*?\/>/gim, '`$1`')
+			.replace(/<Contributors usernames="(.*?)" \/>/gim, (_, p1) => {
+				const users = p1
+					.split(',')
+					.map((e: string) => `[${e}](https://github.com/${e})`);
+				return `Contributors: ${users.join(', ')}`;
+			})
+			.replace(/<p>(.*?)<\/p>/gm, '$1')
+			.replace(/^[\n]+/m, '');
+		if (!info) {
+			return content;
+		}
+
+		return [
+			`# ${info.title}`,
+			`> Published at ${releaseId}, see also https://gitpod.io/changelog`,
+			`![${info.alt ?? 'image'}](https://www.gitpod.io/images/changelog/${info.image})`,
+			content,
+		].join('\n\n');
+	}
+
+	public async updateHtml(releaseId?: string) {
+		if (!releaseId) {
+			releaseId = await getLastPublish(this.cacheHelper);
+		}
+		const mdContent = await this.loadChangelog(releaseId);
+		const html = await vscode.commands.executeCommand('markdown.api.render', mdContent) as string;
+		this.panel.webview.html = `<!DOCTYPE html>
+<html lang="en">
+<head>
+	<meta charset="UTF-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
+	<title>Gitpod Release Notes</title>
+	<style>
+		${DEFAULT_MARKDOWN_STYLES}
+	</style>
+</head>
+	<body>
+		${html}
+	</body>
+</html>`;
+		if (!this.lastReadId || releaseId > this.lastReadId) {
+			await this.context.globalState.update(LAST_READ_RELEASE_NOTES_ID, releaseId);
+			this.lastReadId = releaseId;
+		}
+	}
+
+	public static createOrShow(context: vscode.ExtensionContext, cacheHelper: CacheHelper) {
+		const column = vscode.window.activeTextEditor
+			? vscode.window.activeTextEditor.viewColumn
+			: undefined;
+
+		if (ReleaseNotesPanel.currentPanel) {
+			ReleaseNotesPanel.currentPanel.panel.reveal(column);
+			return;
+		}
+
+		const panel = vscode.window.createWebviewPanel(
+			ReleaseNotesPanel.viewType,
+			'Gitpod Release Notes',
+			column || vscode.ViewColumn.One,
+			{ enableScripts: true },
+		);
+
+		ReleaseNotesPanel.currentPanel = new ReleaseNotesPanel(context, cacheHelper, panel);
+	}
+
+	public static revive(context: vscode.ExtensionContext, cacheHelper: CacheHelper, panel: vscode.WebviewPanel) {
+		ReleaseNotesPanel.currentPanel = new ReleaseNotesPanel(context, cacheHelper, panel);
+	}
+
+	private constructor(
+		private readonly context: vscode.ExtensionContext,
+		private readonly cacheHelper: CacheHelper,
+		panel: vscode.WebviewPanel
+	) {
+		this.lastReadId = this.context.globalState.get<string>(LAST_READ_RELEASE_NOTES_ID);
+		this.panel = panel;
+
+		this.updateHtml();
+
+		this.panel.onDidDispose(() => this.dispose(), null, this._disposables);
+		this.panel.onDidChangeViewState(
+			() => {
+				if (this.panel.visible) {
+					this.updateHtml();
+				}
+			},
+			null,
+			this._disposables
+		);
+	}
+
+	public dispose() {
+		ReleaseNotesPanel.currentPanel = undefined;
+		this.panel.dispose();
+		while (this._disposables.length) {
+			const x = this._disposables.pop();
+			if (x) {
+				x.dispose();
+			}
+		}
+	}
+}
+
+// Align with https://github.com/gitpod-io/openvscode-server/blob/494f7eba3615344ee634e6bec0b20a1903e5881d/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts#L14
+export const DEFAULT_MARKDOWN_STYLES = `
+body {
+	padding: 10px 20px;
+	line-height: 22px;
+	max-width: 882px;
+	margin: 0 auto;
+}
+
+body *:last-child {
+	margin-bottom: 0;
+}
+
+img {
+	max-width: 100%;
+	max-height: 100%;
+}
+
+a {
+	text-decoration: none;
+}
+
+a:hover {
+	text-decoration: underline;
+}
+
+a:focus,
+input:focus,
+select:focus,
+textarea:focus {
+	outline: 1px solid -webkit-focus-ring-color;
+	outline-offset: -1px;
+}
+
+hr {
+	border: 0;
+	height: 2px;
+	border-bottom: 2px solid;
+}
+
+h1 {
+	padding-bottom: 0.3em;
+	line-height: 1.2;
+	border-bottom-width: 1px;
+	border-bottom-style: solid;
+}
+
+h1, h2, h3 {
+	font-weight: normal;
+}
+
+table {
+	border-collapse: collapse;
+}
+
+table > thead > tr > th {
+	text-align: left;
+	border-bottom: 1px solid;
+}
+
+table > thead > tr > th,
+table > thead > tr > td,
+table > tbody > tr > th,
+table > tbody > tr > td {
+	padding: 5px 10px;
+}
+
+table > tbody > tr + tr > td {
+	border-top-width: 1px;
+	border-top-style: solid;
+}
+
+blockquote {
+	margin: 0 7px 0 5px;
+	padding: 0 16px 0 10px;
+	border-left-width: 5px;
+	border-left-style: solid;
+}
+
+code {
+	font-family: "SF Mono", Monaco, Menlo, Consolas, "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace;
+}
+
+pre code {
+	font-family: var(--vscode-editor-font-family);
+	font-weight: var(--vscode-editor-font-weight);
+	font-size: var(--vscode-editor-font-size);
+	line-height: 1.5;
+}
+
+code > div {
+	padding: 16px;
+	border-radius: 3px;
+	overflow: auto;
+}
+
+.monaco-tokenized-source {
+	white-space: pre;
+}
+
+/** Theming */
+
+.vscode-light code > div {
+	background-color: rgba(220, 220, 220, 0.4);
+}
+
+.vscode-dark code > div {
+	background-color: rgba(10, 10, 10, 0.4);
+}
+
+.vscode-high-contrast code > div {
+	background-color: var(--vscode-textCodeBlock-background);
+}
+
+.vscode-high-contrast h1 {
+	border-color: rgb(0, 0, 0);
+}
+
+.vscode-light table > thead > tr > th {
+	border-color: rgba(0, 0, 0, 0.69);
+}
+
+.vscode-dark table > thead > tr > th {
+	border-color: rgba(255, 255, 255, 0.69);
+}
+
+.vscode-light h1,
+.vscode-light hr,
+.vscode-light table > tbody > tr + tr > td {
+	border-color: rgba(0, 0, 0, 0.18);
+}
+
+.vscode-dark h1,
+.vscode-dark hr,
+.vscode-dark table > tbody > tr + tr > td {
+	border-color: rgba(255, 255, 255, 0.18);
+}
+
+`;
diff --git a/extensions/gitpod-web/package.json b/extensions/gitpod-web/package.json
index db5f9c7846d57..367d23ff9eba8 100644
--- a/extensions/gitpod-web/package.json
+++ b/extensions/gitpod-web/package.json
@@ -41,6 +41,11 @@
         "title": "%stopWorkspace%",
         "enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true"
       },
+	  {
+		"command": "gitpod.showReleaseNotes",
+		"title": "%showReleaseNotes%",
+		"enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true"
+	  },
       {
         "command": "gitpod.open.settings",
         "title": "%openSettings%",
@@ -81,6 +86,11 @@
         "title": "%reportIssue%",
         "enablement": "gitpod.inWorkspace == true"
       },
+      {
+        "command": "gitpod.showReleaseNotes",
+        "title": "%showReleaseNotes%",
+        "enablement": "gitpod.inWorkspace == true"
+      },
       {
         "command": "gitpod.upgradeSubscription",
         "title": "%upgradeSubscription%",
@@ -244,6 +254,10 @@
         {
           "command": "gitpod.reportIssue",
           "group": "z_about2@40"
+        },
+        {
+          "command": "gitpod.showReleaseNotes",
+          "group": "z_about2@50"
         }
       ],
       "extension/context": [
@@ -394,6 +408,11 @@
           "group": "remote_00_gitpod_navigation@130",
           "when": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true && gitpod.workspaceShared == true"
         },
+        {
+          "command": "gitpod.showReleaseNotes",
+          "group": "remote_00_gitpod_navigation@140",
+          "when": "gitpod.inWorkspace == true"
+        },
         {
           "command": "gitpod.openInStable",
           "group": "remote_00_gitpod_navigation@900",
diff --git a/extensions/gitpod-web/package.nls.json b/extensions/gitpod-web/package.nls.json
index 572ce136ce55b..412a9fe82625f 100644
--- a/extensions/gitpod-web/package.nls.json
+++ b/extensions/gitpod-web/package.nls.json
@@ -20,6 +20,7 @@
 	"openTwitter": "Gitpod: Follow us on Twitter",
 	"reportIssue": "Gitpod: Report Issue",
 	"stopWorkspace": "Gitpod: Stop Workspace",
+	"showReleaseNotes": "Gitpod: Show Release Notes",
 	"upgradeSubscription": "Gitpod: Upgrade Subscription",
 	"extendTimeout": "Gitpod: Extend Workspace Timeout",
 	"takeSnapshot": "Gitpod: Share Workspace Snapshot",
diff --git a/extensions/gitpod-web/src/extension.ts b/extensions/gitpod-web/src/extension.ts
index 1f3a68f2dd99c..d6ea24731c3a2 100644
--- a/extensions/gitpod-web/src/extension.ts
+++ b/extensions/gitpod-web/src/extension.ts
@@ -9,7 +9,7 @@ import * as grpc from '@grpc/grpc-js';
 import * as fs from 'fs';
 import * as os from 'os';
 import * as uuid from 'uuid';
-import { GitpodPluginModel, GitpodExtensionContext, setupGitpodContext, registerTasks, registerIpcHookCli } from 'gitpod-shared';
+import { GitpodPluginModel, GitpodExtensionContext, setupGitpodContext, registerTasks, registerIpcHookCli, registerReleaseNotesView } from 'gitpod-shared';
 import { GetTokenRequest } from '@gitpod/supervisor-api-grpc/lib/token_pb';
 import { PortsStatus, ExposedPortInfo, PortsStatusRequest, PortsStatusResponse, PortVisibility, OnPortExposedAction } from '@gitpod/supervisor-api-grpc/lib/status_pb';
 import { TunnelVisiblity, TunnelPortRequest, RetryAutoExposeRequest, CloseTunnelRequest } from '@gitpod/supervisor-api-grpc/lib/port_pb';
@@ -49,6 +49,7 @@ export async function activate(context: vscode.ExtensionContext) {
 
 	registerIpcHookCli(gitpodContext);
 	registerExtensionManagement(gitpodContext);
+	registerReleaseNotesView(gitpodContext);
 	await gitpodContext.active;
 }
 
diff --git a/extensions/yarn.lock b/extensions/yarn.lock
index 9e707900b0a07..9dd805b657ab1 100644
--- a/extensions/yarn.lock
+++ b/extensions/yarn.lock
@@ -125,6 +125,11 @@
     component-type "^1.2.1"
     join-component "^1.1.0"
 
+"@types/js-yaml@^4.0.5":
+  version "4.0.5"
+  resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138"
+  integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==
+
 "@types/long@^4.0.1":
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
@@ -1019,7 +1024,7 @@ join-component@^1.1.0:
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
   integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
 
-js-yaml@4.1.0:
+js-yaml@4.1.0, js-yaml@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
   integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==