diff --git a/docusaurus/docs/main-concept/build-config.md b/docusaurus/docs/main-concept/build-config.md
index a064ec1..54ba086 100644
--- a/docusaurus/docs/main-concept/build-config.md
+++ b/docusaurus/docs/main-concept/build-config.md
@@ -34,9 +34,11 @@ There's several configuration that could be setup here:
- `publicPath` - This value would override publicPath definition for your asset files.
- `client` - This value would be merged to Treats client Webpack configuration using [webpack-merge][webpack-merge-website]
- `server` - This value would be merged to Treats server Webpack configuration using [webpack-merge][webpack-merge-website]
+ - `workbox` - This configuration can be used to enable and setting workbox configuration in treats. More info on workbox configuration can be seen on [here][workbox-build-configuration]
- `postcss` -This configuration can be used to extends Treats PostCSS setup
- `babel` -This configuration can be used to extends Treats Babel setup. All values would be merged to treats babel config using [babel-merge][babel-merge-website]
[webpack-merge-website]: https://www.npmjs.com/package/webpack-merge
[babel-merge-website]: https://www.npmjs.com/package/babel-merge
+[workbox-build-configuration]: ./workbox.html
diff --git a/docusaurus/docs/main-concept/workbox.md b/docusaurus/docs/main-concept/workbox.md
new file mode 100644
index 0000000..984c18b
--- /dev/null
+++ b/docusaurus/docs/main-concept/workbox.md
@@ -0,0 +1,41 @@
+---
+id: workbox
+title: Treats with Workbox
+sidebar_label: Workbox
+---
+Treats provides [Workbox][workbox-main-page] support in building your application. Workbox is a libary that makes caching assets on your application much easier so it can improve your application's performance and resilience in unstable condition.
+
+Treats using a webpack plugin called [workbox-webpack-plugin][workbox-webpack-plugin-module-page] to implement Workbox. Workbox configuration can be set and enabled on your project from your project's treats build config (`treats.config.js`) as can be seen in here [build config][main-concept-build-config] file without needing to install and add any of workbox dependencies.
+
+## Configuring Workbox inside Treats Build Config file
+Here's an example on how to enable your workbox configuration on `treats.config.js`:
+```
+// treats.config.js
+...
+const config: {
+ ...
+ webpack: {
+ ...
+ workbox: {
+ pluginMode: "InjectManifest",
+ serviceWorkerFilename: "sw.js",
+ options: {
+ swSrc: "./src/sw.js",
+ include: /\.(html|css|js)$/
+ }
+ }
+ }
+}
+
+```
+Your configuration should be placed inside `workbox` object inside of `webpack`'s config. There's several variable that can be inputted here:
+- `pluginMode`: plugin classes that are provided by `workbox-webpack-plugin`. There's two plugins that can be used such as:
+ - `GenerateSW`: Automatically generate a service worker.
+ - `InjectManifest`: Injecting list of precached assets into a service worker file. If you're using this plugin, `swSrc` must be included in option.
+- `serviceWorkerFilename`: The name of the service worker output file. Will be defaulted to `service-worker.js` if this variable left empty.
+- `options`: Configuration options that to be added as the plugin's option in `workbox-webpack-plugin`. More info on what options that available to be added can be found here.
+
+
+[workbox-main-page]: https://developers.google.com/web/tools/workbox/
+[workbox-webpack-plugin-module-page]: https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin
+[main-concept-build-config]: ./build-config.html
\ No newline at end of file
diff --git a/docusaurus/website/sidebars.json b/docusaurus/website/sidebars.json
index 09d832c..ca4a03b 100644
--- a/docusaurus/website/sidebars.json
+++ b/docusaurus/website/sidebars.json
@@ -29,7 +29,8 @@
"main-concept/generator",
"main-concept/scripts",
"main-concept/addons",
- "main-concept/typescript"
+ "main-concept/typescript",
+ "main-concept/workbox"
],
"API Reference": [
"api-reference/overview",
diff --git a/example/app-with-workbox/README.md b/example/app-with-workbox/README.md
new file mode 100644
index 0000000..cd8e857
--- /dev/null
+++ b/example/app-with-workbox/README.md
@@ -0,0 +1,3 @@
+# App with Workbox Examples
+
+This directory contains examples on using workbox in Treats. Separated into two plugins which are GenerateSW and InjectManifest.
\ No newline at end of file
diff --git a/example/app-with-workbox/generate-sw/package.json b/example/app-with-workbox/generate-sw/package.json
new file mode 100644
index 0000000..23ed9bf
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "app-with-workbox",
+ "version": "0.0.1",
+ "description": "My First Treats App",
+ "license": "ISC",
+ "scripts": {
+ "start": "treats start",
+ "build:client": "treats build --target client",
+ "build:server": "treats build --target server",
+ "build": "treats build",
+ "clean": "treats clean",
+ "generate": "treats generate",
+ "analyze:client": "treats build --target client --analyze",
+ "analyze:server": "treats build --target server --analyze",
+ "profile": "yarn build:server && node --prof dist/server.js",
+ "documentation:build": "treats documentation build src/",
+ "documentation:lint": "treats documentation lint src/",
+ "documentation:phriction": "treats documentation export src/ --target phriction",
+ "documentation:flush": "treats documentation flush src/",
+ "test": "treats test",
+ "test:watch": "treats test --watchAll",
+ "test:coverage": "treats test --coverage"
+ },
+ "dependencies": {
+ "treats": "0.2.0"
+ }
+}
diff --git a/example/app-with-workbox/generate-sw/src/_locale/en.json b/example/app-with-workbox/generate-sw/src/_locale/en.json
new file mode 100644
index 0000000..2712f04
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/_locale/en.json
@@ -0,0 +1,4 @@
+{
+ "welcome_page__description1": "A development kit to make your experience on building fully customizable {React} app with built-in Server-side rendering, Code-splitting, i18n, {Redux} and {GraphQL} sweeter!",
+ "welcome_page__description2": "To get started, edit {Source} and save to reload, or learn more on our {Documentation}"
+}
diff --git a/example/app-with-workbox/generate-sw/src/_locale/id.json b/example/app-with-workbox/generate-sw/src/_locale/id.json
new file mode 100644
index 0000000..789d228
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/_locale/id.json
@@ -0,0 +1,4 @@
+{
+ "welcome_page__description1": "Sebuah development kit untuk membuat pengalaman anda dalam membangun sebuah aplikasi {React} yang sangat mudah dikustomisasi dengan Server-side rendering, Code-splitting, i18n, {Redux} dan {GraphQL} jadi lebih manis!",
+ "welcome_page__description2": "Untuk memulai, sunting {Source} dan simpan untuk me-reload, atau pelajari lebih lanjut di {Documentation} kami."
+}
diff --git a/example/app-with-workbox/generate-sw/src/_locale/index.js b/example/app-with-workbox/generate-sw/src/_locale/index.js
new file mode 100644
index 0000000..aaa9091
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/_locale/index.js
@@ -0,0 +1,7 @@
+import en from "./en.json";
+import id from "./id.json";
+
+export default {
+ en,
+ id
+};
diff --git a/example/app-with-workbox/generate-sw/src/_route/module.js b/example/app-with-workbox/generate-sw/src/_route/module.js
new file mode 100644
index 0000000..6bf78f5
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/_route/module.js
@@ -0,0 +1,9 @@
+import Welcome from "@page/welcome";
+
+import { WELCOME } from "./path";
+
+const module = {
+ [WELCOME]: Welcome
+};
+
+export default module;
diff --git a/example/app-with-workbox/generate-sw/src/_route/path.js b/example/app-with-workbox/generate-sw/src/_route/path.js
new file mode 100644
index 0000000..de3c00c
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/_route/path.js
@@ -0,0 +1 @@
+export const WELCOME = "/";
diff --git a/example/app-with-workbox/generate-sw/src/_route/route.js b/example/app-with-workbox/generate-sw/src/_route/route.js
new file mode 100644
index 0000000..fda5c99
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/_route/route.js
@@ -0,0 +1,12 @@
+import { WELCOME } from "./path";
+
+const route = [
+ {
+ name: "welcome",
+ path: WELCOME,
+ exact: true,
+ disabled: true
+ }
+];
+
+export default route;
diff --git a/example/app-with-workbox/generate-sw/src/page/welcome/NotoSans-Bold.ttf b/example/app-with-workbox/generate-sw/src/page/welcome/NotoSans-Bold.ttf
new file mode 100644
index 0000000..1db7886
Binary files /dev/null and b/example/app-with-workbox/generate-sw/src/page/welcome/NotoSans-Bold.ttf differ
diff --git a/example/app-with-workbox/generate-sw/src/page/welcome/NotoSans-Regular.ttf b/example/app-with-workbox/generate-sw/src/page/welcome/NotoSans-Regular.ttf
new file mode 100644
index 0000000..0a01a06
Binary files /dev/null and b/example/app-with-workbox/generate-sw/src/page/welcome/NotoSans-Regular.ttf differ
diff --git a/example/app-with-workbox/generate-sw/src/page/welcome/index.js b/example/app-with-workbox/generate-sw/src/page/welcome/index.js
new file mode 100644
index 0000000..a2e0a68
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/page/welcome/index.js
@@ -0,0 +1,5 @@
+import AsyncLoader from "@treats/component/async-loader";
+
+const Welcome = AsyncLoader({ component: import("./welcome") });
+
+export default Welcome;
diff --git a/example/app-with-workbox/generate-sw/src/page/welcome/treats.png b/example/app-with-workbox/generate-sw/src/page/welcome/treats.png
new file mode 100644
index 0000000..bc3b5f2
Binary files /dev/null and b/example/app-with-workbox/generate-sw/src/page/welcome/treats.png differ
diff --git a/example/app-with-workbox/generate-sw/src/page/welcome/welcome.css b/example/app-with-workbox/generate-sw/src/page/welcome/welcome.css
new file mode 100644
index 0000000..ee9943c
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/page/welcome/welcome.css
@@ -0,0 +1,88 @@
+@font-face {
+ font-family: "Noto Sans";
+ src: url("./NotoSans-Bold.ttf");
+ font-weight: bold;
+}
+@font-face {
+ font-family: "Noto Sans";
+ src: url("./NotoSans-Regular.ttf");
+ font-weight: normal;
+}
+
+a {
+ color: #42b549;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #ff5722;
+}
+
+.welcome_page {
+ position: relative;
+ display: block;
+ font-family: "Noto Sans", sans-serif;
+ text-align: center;
+ height: 700px;
+ white-space: nowrap;
+ padding: 0 30px;
+}
+
+.welcome_page:before {
+ content: "";
+ display: inline-block;
+ vertical-align: middle;
+ height: 100%;
+ width: 0;
+}
+
+.welcome_page__content {
+ display: inline-block;
+ vertical-align: middle;
+ white-space: normal;
+ width: 100%;
+}
+
+.welcome_page__toped {
+ width: 200px;
+}
+.welcome_page__locale_switcher_container {
+ position: relative;
+ white-space: nowrap;
+ padding-top: 20px;
+ font-size: 12px;
+}
+
+.welcome_page__locale_switcher {
+ display: inline-block;
+ vertical-align: middle;
+ padding: 10px;
+ min-width: 100px;
+ background: #fff;
+ color: #42b549;
+ border: 1px solid #f0f0f0;
+}
+
+.welcome_page__locale_switcher:hover {
+ color: #42b549;
+ background: #EEE;
+}
+
+.welcome_page__locale_switcher:global(.active) {
+ background: #42b549;
+ color: #fff;
+}
+
+.welcome_page__locale_switcher:first-child {
+ border-top-left-radius: 30px;
+ border-bottom-left-radius: 30px;
+}
+
+.welcome_page__locale_switcher:last-child {
+ border-top-right-radius: 30px;
+ border-bottom-right-radius: 30px;
+}
+
+.welcome_page__locale_switcher:global(.active):hover {
+ color: #FFF;
+}
diff --git a/example/app-with-workbox/generate-sw/src/page/welcome/welcome.js b/example/app-with-workbox/generate-sw/src/page/welcome/welcome.js
new file mode 100644
index 0000000..2e364b5
--- /dev/null
+++ b/example/app-with-workbox/generate-sw/src/page/welcome/welcome.js
@@ -0,0 +1,82 @@
+import React from "react";
+import Helmet from "@treats/helmet";
+import { FormattedMessage, injectIntl } from "@treats/intl";
+import AsyncComponent from "@treats/component/async-component";
+
+import style from "./welcome.css";
+import treats from "./treats.png";
+
+/**
+ * Welcome to treats component
+ * @param props React props
+ * @param props.intl Intl Object
+ * @author Tokopedia Engineering
+ */
+const Welcome = ({ intl }) => (
+