diff --git a/pattern-shaka-video-player/.gitignore b/pattern-shaka-video-player/.gitignore
new file mode 100644
index 00000000..49c03385
--- /dev/null
+++ b/pattern-shaka-video-player/.gitignore
@@ -0,0 +1,15 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# dependencies
+node_modules
+
+# testing
+coverage
+
+# production
+build
+dist
+
+# misc
+.DS_Store
+npm-debug.log
diff --git a/pattern-shaka-video-player/README.md b/pattern-shaka-video-player/README.md
new file mode 100644
index 00000000..6ff842de
--- /dev/null
+++ b/pattern-shaka-video-player/README.md
@@ -0,0 +1,9 @@
+## Shaka Video Player pattern
+
+A sample Enact application that demonstrates how to use [shaka-player](https://shaka-player-demo.appspot.com/docs/api/index.html).
+
+Run `npm install` then `npm run serve` to have the app running on [http://localhost:8080](http://localhost:8080), where you can view it in your browser.
+
+---
+
+This project was bootstrapped with the Enact [cli](https://github.com/enactjs/cli).
diff --git a/pattern-shaka-video-player/package.json b/pattern-shaka-video-player/package.json
new file mode 100644
index 00000000..e60b0769
--- /dev/null
+++ b/pattern-shaka-video-player/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "shaka-app",
+ "version": "1.0.0",
+ "description": "A sample Enact app that showcases a VideoPlayer powered by Shaka Player",
+ "author": "@teckliew",
+ "main": "src/index.js",
+ "scripts": {
+ "serve": "enact serve",
+ "pack": "enact pack",
+ "pack-p": "enact pack -p",
+ "watch": "enact pack --watch",
+ "clean": "enact clean",
+ "lint": "enact lint .",
+ "license": "enact license",
+ "test": "enact test",
+ "test-watch": "enact test --watch"
+ },
+ "license": "Apache-2.0",
+ "private": true,
+ "repository": "",
+ "enact": {
+ "theme": "moonstone"
+ },
+ "eslintConfig": {
+ "extends": "enact"
+ },
+ "eslintIgnore": [
+ "node_modules/*",
+ "build/*",
+ "dist/*"
+ ],
+ "dependencies": {
+ "@enact/core": "^3.0.0-beta.1",
+ "@enact/i18n": "^3.0.0-beta.1",
+ "@enact/moonstone": "^3.0.0-beta.1",
+ "@enact/spotlight": "^3.0.0-beta.1",
+ "@enact/ui": "^2.0.0",
+ "ilib": "^14.3.0",
+ "prop-types": "^15.6.2",
+ "react": "^16.8.0",
+ "react-dom": "^16.8.0",
+ "shaka-player": "^2.5.2"
+ }
+}
diff --git a/pattern-shaka-video-player/resources/ilibmanifest.json b/pattern-shaka-video-player/resources/ilibmanifest.json
new file mode 100644
index 00000000..5916671d
--- /dev/null
+++ b/pattern-shaka-video-player/resources/ilibmanifest.json
@@ -0,0 +1,3 @@
+{
+ "files": []
+}
\ No newline at end of file
diff --git a/pattern-shaka-video-player/src/App/App.js b/pattern-shaka-video-player/src/App/App.js
new file mode 100644
index 00000000..960f23e7
--- /dev/null
+++ b/pattern-shaka-video-player/src/App/App.js
@@ -0,0 +1,27 @@
+import kind from '@enact/core/kind';
+import MoonstoneDecorator from '@enact/moonstone/MoonstoneDecorator';
+import Panels from '@enact/moonstone/Panels';
+import React from 'react';
+
+import MainPanel from '../views/MainPanel';
+
+import css from './App.module.less';
+
+const App = kind({
+ name: 'App',
+
+ styles: {
+ css,
+ className: 'app'
+ },
+
+ render: (props) => (
+
+ )
+});
+
+export default MoonstoneDecorator(App);
diff --git a/pattern-shaka-video-player/src/App/App.module.less b/pattern-shaka-video-player/src/App/App.module.less
new file mode 100644
index 00000000..23782def
--- /dev/null
+++ b/pattern-shaka-video-player/src/App/App.module.less
@@ -0,0 +1,3 @@
+.app {
+ // styles can be put here
+}
diff --git a/pattern-shaka-video-player/src/App/package.json b/pattern-shaka-video-player/src/App/package.json
new file mode 100644
index 00000000..add0ba2a
--- /dev/null
+++ b/pattern-shaka-video-player/src/App/package.json
@@ -0,0 +1,3 @@
+{
+ "main": "App.js"
+}
\ No newline at end of file
diff --git a/pattern-shaka-video-player/src/components/ShakaVideoPlayer.js b/pattern-shaka-video-player/src/components/ShakaVideoPlayer.js
new file mode 100644
index 00000000..1cba3b0d
--- /dev/null
+++ b/pattern-shaka-video-player/src/components/ShakaVideoPlayer.js
@@ -0,0 +1,89 @@
+import {forward, handle} from '@enact/core/handle';
+import hoc from '@enact/core/hoc';
+import VideoPlayer from "@enact/moonstone/VideoPlayer";
+import PropTypes from 'prop-types';
+import React from 'react';
+import shaka from 'shaka-player';
+
+const ShakaVideoPlayerDecorator = hoc((config, Wrapped) => {
+ return class extends React.Component {
+ static displayName = 'ShakaVideoPlayerDecorator'
+
+ static propTypes = {
+ config: PropTypes.object,
+ manifestUri: PropTypes.string,
+ onError: PropTypes.func
+ }
+
+ componentDidMount () {
+ // Install built-in polyfills to patch browser incompatibilities.
+ shaka.polyfill.installAll();
+
+ // Check to see if the browser supports the basic APIs Shaka needs.
+ if (shaka.Player.isBrowserSupported()) {
+ // Everything looks good!
+ this.initPlayer();
+ } else {
+ // This browser does not have the minimum set of APIs we need.
+ console.error('Browser not supported!');
+ }
+ }
+
+ onErrorEvent = (event) => {
+ // Extract the shaka.util.Error object from the event.
+ this.onError(event.detail);
+ }
+
+ onError = handle(
+ forward('onError')
+ ).bindAs(this, 'onError')
+
+ initPlayer = () => {
+ // Create a Player instance with videoNode.
+ const player = new shaka.Player(this.videoNode);
+
+ // Listen for error events.
+ player.addEventListener('error', this.onErrorEvent);
+
+ // Try to load a manifest.
+ // This is an asynchronous process.
+ player
+ .load(this.props.manifestUri)
+ .then(function () {
+ // This runs if the asynchronous load is successful.
+ console.log('The video has now been loaded!');
+ })
+ .catch(this.onError); // onError is executed if the asynchronous load fails.
+
+ // Configuration for the player here
+ // https://shaka-player-demo.appspot.com/docs/api/tutorial-config.html
+ const playerConfig = {...config, ...this.props.config};
+ player.configure(playerConfig);
+ }
+
+ setWrappedRef = (node) => {
+ if (node && node.getVideoNode) {
+ // By default, moonstone/VideoPlayer uses ui/Media for its videoComponent. To get
+ // the underlying