diff --git a/electron.js b/electron.js
index 214dbe1..8fafc22 100644
--- a/electron.js
+++ b/electron.js
@@ -143,6 +143,12 @@ app.on('ready', () => {
 		}
 	]);
 	Menu.setApplicationMenu(mainMenu);
+
+	app.on('open-url', (event, url) => {
+		event.preventDefault();
+
+		win.webContents.send('open-url', url);
+	});
 });
 
 // Quit when all windows are closed.
diff --git a/src/App.js b/src/App.js
index 4c2c0dd..060d60f 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,6 +4,7 @@ import { connect } from 'react-redux';
 
 import { hideModal, showModal } from './lib/actions';
 import CreateModal from './CreateModal';
+import Extensions from './Extensions';
 import Header from './Header';
 import Installer from './Installer';
 import MachineList from './MachineList';
@@ -33,6 +34,10 @@ class App extends Component {
 				modalComponent = ;
 				break;
 
+			case 'extensions':
+				modalComponent = ;
+				break;
+
 			default:
 				// No-op
 				break;
diff --git a/src/Extensions.css b/src/Extensions.css
new file mode 100644
index 0000000..1ae1c30
--- /dev/null
+++ b/src/Extensions.css
@@ -0,0 +1,68 @@
+.Extensions {
+	display: flex;
+	flex-direction: column;
+}
+.Extensions .Header .search {
+	background: rgba(255, 255, 255, 0.1);
+	border: 1px solid rgba(255, 255, 255, 0.1);
+	border-radius: 4px;
+	color: #fff;
+	font-size: 1rem;
+	padding: 0.3rem 0.4rem;
+}
+.Extensions .Header .search::-webkit-input-placeholder {
+	color: rgba(255, 255, 255, 0.75);
+}
+.Extensions .Header .search:focus {
+	outline: 0;
+	border-color: rgba(255, 255, 255, 0.5);
+}
+.extensions-list {
+	list-style: none;
+	padding: 0.5rem 0.5rem 0;
+	margin: 0;
+
+	overflow-y: scroll;
+	flex-grow: 1;
+
+	font-size: 14px;
+	display: flex;
+	flex-direction: column;
+}
+.extensions-list li {
+	border: 1px solid #ccc;
+	border-radius: 0.3em;
+	padding: 1em;
+	margin-bottom: 1em;
+	flex-shrink: 0;
+	transition: transform 100ms, opacity 130ms;
+	display: flex;
+}
+.extensions-list li > :first-child {
+	flex-grow: 1;
+}
+.extensions-list li.no-match {
+	// transform: scale(0.5, 0.5);
+	opacity: 0;
+	order: 5;
+}
+.extensions-list h2 {
+	margin: 0 0 0.3em;
+	font-size: 1.3em;
+}
+.extensions-list p {
+	margin: 0 0 0.6em;
+}
+.extensions-list .author {
+	color: #888;
+	margin-bottom: 0;
+}
+.extensions-list .author img {
+	width: 28px;
+	height: 28px;
+	background: var(--color-primary);
+	padding: 2px;
+	vertical-align: middle;
+	margin-right: 0.5em;
+	border-radius: 4px;
+}
diff --git a/src/Extensions.js b/src/Extensions.js
new file mode 100644
index 0000000..393fbd0
--- /dev/null
+++ b/src/Extensions.js
@@ -0,0 +1,94 @@
+import React from 'react';
+
+import Button from './Button';
+import Header from './Header';
+
+import './Extensions.css';
+
+const EXTENSIONS_INDEX = 'http://beta.chassis.io/extensions.json';
+
+export default class Extensions extends React.Component {
+	constructor( props ) {
+		super( props );
+
+		this.state = {
+			available: [],
+			loading: true,
+			search: '',
+		};
+
+		this.loadExtensions();
+	}
+
+	loadExtensions() {
+		fetch( EXTENSIONS_INDEX )
+			.then( resp => resp.json() )
+			.then( available => this.setState({ available, loading: false }) );
+	}
+
+	render() {
+		const { onDismiss } = this.props;
+		const { available, loading, search } = this.state;
+
+		const withAuthors = available.map(item => {
+			const author = {
+				name: 'Chassis',
+				avatar: '/logo.png',
+			};
+
+			return { ...item, author };
+		})
+
+		const filtered = search === '' ? withAuthors : withAuthors.map( item => {
+			const searchable = item.name + ' ' + item.description;
+			console.log( searchable.toLowerCase().indexOf( search.toLowerCase() ) !== -1 );
+			return { ...item, matched: searchable.toLowerCase().indexOf( search.toLowerCase() ) !== -1 };
+		});
+		filtered.map( item => console.log( item.name, search && ! item.matched ) );
+
+		return 
+			
+
+			{ loading ?
+				
Loading…
+			:
+				
+					{ filtered.map( extension =>
+						- 
+							
+								 { extension.name }
+								 { extension.description } 
+								 
+									 +									{ extension.author.name }
+ +									{ extension.author.name }
+
 
+							 
+								
+							 +
+					) }
+
+			}
+