diff --git a/examples/soap-calculator/public/index.html b/examples/soap-calculator/public/index.html
new file mode 100644
index 000000000000..897347d65ba9
--- /dev/null
+++ b/examples/soap-calculator/public/index.html
@@ -0,0 +1,73 @@
+
+
+
+
+ @loopback/example-soap-calculator
+
+
+
+
+
+
+
+
+
+
+
+
@loopback/example-soap-calculator
+
+
+
+
+
+
+
+
diff --git a/examples/soap-calculator/src/controllers/home-page.controller.ts b/examples/soap-calculator/src/controllers/home-page.controller.ts
new file mode 100644
index 000000000000..f78f989e4632
--- /dev/null
+++ b/examples/soap-calculator/src/controllers/home-page.controller.ts
@@ -0,0 +1,31 @@
+import {get} from '@loopback/openapi-v3';
+import * as fs from 'fs';
+import * as path from 'path';
+import {inject} from '@loopback/context';
+import {RestBindings, Response} from '@loopback/rest';
+
+export class HomePageController {
+ private html: string;
+ constructor(@inject(RestBindings.Http.RESPONSE) private response: Response) {
+ this.html = fs.readFileSync(
+ path.join(__dirname, '../../../public/index.html'),
+ 'utf-8',
+ );
+ }
+
+ @get('/', {
+ responses: {
+ '200': {
+ description: 'Home Page',
+ content: {'text/html': {schema: {type: 'string'}}},
+ },
+ },
+ })
+ homePage() {
+ this.response
+ .status(200)
+ .contentType('html')
+ .send(this.html);
+ return this.response;
+ }
+}
diff --git a/examples/soap-calculator/src/index.ts b/examples/soap-calculator/src/index.ts
index 085d48b9099d..c18374f67d07 100644
--- a/examples/soap-calculator/src/index.ts
+++ b/examples/soap-calculator/src/index.ts
@@ -1,6 +1,8 @@
import {SoapCalculatorApplication} from './application';
import {ApplicationConfig} from '@loopback/core';
+export {SoapCalculatorApplication};
+
export async function main(options: ApplicationConfig = {}) {
const app = new SoapCalculatorApplication(options);
await app.boot();
diff --git a/examples/soap-calculator/test/acceptance/home-page.controller.acceptance.ts b/examples/soap-calculator/test/acceptance/home-page.controller.acceptance.ts
new file mode 100644
index 000000000000..f78f989e4632
--- /dev/null
+++ b/examples/soap-calculator/test/acceptance/home-page.controller.acceptance.ts
@@ -0,0 +1,31 @@
+import {get} from '@loopback/openapi-v3';
+import * as fs from 'fs';
+import * as path from 'path';
+import {inject} from '@loopback/context';
+import {RestBindings, Response} from '@loopback/rest';
+
+export class HomePageController {
+ private html: string;
+ constructor(@inject(RestBindings.Http.RESPONSE) private response: Response) {
+ this.html = fs.readFileSync(
+ path.join(__dirname, '../../../public/index.html'),
+ 'utf-8',
+ );
+ }
+
+ @get('/', {
+ responses: {
+ '200': {
+ description: 'Home Page',
+ content: {'text/html': {schema: {type: 'string'}}},
+ },
+ },
+ })
+ homePage() {
+ this.response
+ .status(200)
+ .contentType('html')
+ .send(this.html);
+ return this.response;
+ }
+}
diff --git a/examples/soap-calculator/test/acceptance/test-helper.ts b/examples/soap-calculator/test/acceptance/test-helper.ts
new file mode 100644
index 000000000000..832633a628aa
--- /dev/null
+++ b/examples/soap-calculator/test/acceptance/test-helper.ts
@@ -0,0 +1,24 @@
+import {SoapCalculatorApplication} from '../..';
+import {
+ createRestAppClient,
+ givenHttpServerConfig,
+ Client,
+} from '@loopback/testlab';
+
+export async function setupApplication(): Promise {
+ const app = new SoapCalculatorApplication({
+ rest: givenHttpServerConfig(),
+ });
+
+ await app.boot();
+ await app.start();
+
+ const client = createRestAppClient(app);
+
+ return {app, client};
+}
+
+export interface AppWithClient {
+ app: SoapCalculatorApplication;
+ client: Client;
+}
diff --git a/examples/todo-list/public/index.html b/examples/todo-list/public/index.html
new file mode 100644
index 000000000000..6866afbe8e15
--- /dev/null
+++ b/examples/todo-list/public/index.html
@@ -0,0 +1,72 @@
+
+
+
+
+ myapp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/todo-list/src/controllers/home-page.controller.ts b/examples/todo-list/src/controllers/home-page.controller.ts
new file mode 100644
index 000000000000..f78f989e4632
--- /dev/null
+++ b/examples/todo-list/src/controllers/home-page.controller.ts
@@ -0,0 +1,31 @@
+import {get} from '@loopback/openapi-v3';
+import * as fs from 'fs';
+import * as path from 'path';
+import {inject} from '@loopback/context';
+import {RestBindings, Response} from '@loopback/rest';
+
+export class HomePageController {
+ private html: string;
+ constructor(@inject(RestBindings.Http.RESPONSE) private response: Response) {
+ this.html = fs.readFileSync(
+ path.join(__dirname, '../../../public/index.html'),
+ 'utf-8',
+ );
+ }
+
+ @get('/', {
+ responses: {
+ '200': {
+ description: 'Home Page',
+ content: {'text/html': {schema: {type: 'string'}}},
+ },
+ },
+ })
+ homePage() {
+ this.response
+ .status(200)
+ .contentType('html')
+ .send(this.html);
+ return this.response;
+ }
+}
diff --git a/examples/todo-list/src/index.ts b/examples/todo-list/src/index.ts
index a42a2f7614db..6683b3f4c20e 100644
--- a/examples/todo-list/src/index.ts
+++ b/examples/todo-list/src/index.ts
@@ -6,6 +6,8 @@
import {TodoListApplication} from './application';
import {ApplicationConfig} from '@loopback/core';
+export {TodoListApplication};
+
export async function main(options: ApplicationConfig = {}) {
const app = new TodoListApplication(options);
await app.boot();
diff --git a/examples/todo-list/test/acceptance/home-page.controller.acceptance.ts b/examples/todo-list/test/acceptance/home-page.controller.acceptance.ts
new file mode 100644
index 000000000000..03c0d6f1e63e
--- /dev/null
+++ b/examples/todo-list/test/acceptance/home-page.controller.acceptance.ts
@@ -0,0 +1,28 @@
+// Copyright IBM Corp. 2018. All Rights Reserved.
+// Node module: @loopback/example-shopping
+// This file is licensed under the MIT License.
+// License text available at https://opensource.org/licenses/MIT
+
+import {Client} from '@loopback/testlab';
+import {TodoListApplication} from '../..';
+import {setupApplication} from './test-helper';
+
+describe('HomePageController', () => {
+ let app: TodoListApplication;
+ let client: Client;
+
+ before('setupApplication', async () => {
+ ({app, client} = await setupApplication());
+ });
+
+ after(async () => {
+ await app.stop();
+ });
+
+ it('exposes a default home page', async () => {
+ await client
+ .get('/')
+ .expect(200)
+ .expect('Content-Type', /text\/html/);
+ });
+});
diff --git a/examples/todo-list/test/acceptance/test-helper.ts b/examples/todo-list/test/acceptance/test-helper.ts
new file mode 100644
index 000000000000..46f0b1c3b6fe
--- /dev/null
+++ b/examples/todo-list/test/acceptance/test-helper.ts
@@ -0,0 +1,24 @@
+import {TodoListApplication} from '../..';
+import {
+ createRestAppClient,
+ givenHttpServerConfig,
+ Client,
+} from '@loopback/testlab';
+
+export async function setupApplication(): Promise {
+ const app = new TodoListApplication({
+ rest: givenHttpServerConfig(),
+ });
+
+ await app.boot();
+ await app.start();
+
+ const client = createRestAppClient(app);
+
+ return {app, client};
+}
+
+export interface AppWithClient {
+ app: TodoListApplication;
+ client: Client;
+}
diff --git a/examples/todo/public/index.html b/examples/todo/public/index.html
new file mode 100644
index 000000000000..fbd397991eb7
--- /dev/null
+++ b/examples/todo/public/index.html
@@ -0,0 +1,73 @@
+
+
+
+
+ @loopback/example-todo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/todo/src/controllers/home-page.controller.ts b/examples/todo/src/controllers/home-page.controller.ts
new file mode 100644
index 000000000000..f78f989e4632
--- /dev/null
+++ b/examples/todo/src/controllers/home-page.controller.ts
@@ -0,0 +1,31 @@
+import {get} from '@loopback/openapi-v3';
+import * as fs from 'fs';
+import * as path from 'path';
+import {inject} from '@loopback/context';
+import {RestBindings, Response} from '@loopback/rest';
+
+export class HomePageController {
+ private html: string;
+ constructor(@inject(RestBindings.Http.RESPONSE) private response: Response) {
+ this.html = fs.readFileSync(
+ path.join(__dirname, '../../../public/index.html'),
+ 'utf-8',
+ );
+ }
+
+ @get('/', {
+ responses: {
+ '200': {
+ description: 'Home Page',
+ content: {'text/html': {schema: {type: 'string'}}},
+ },
+ },
+ })
+ homePage() {
+ this.response
+ .status(200)
+ .contentType('html')
+ .send(this.html);
+ return this.response;
+ }
+}
diff --git a/examples/todo/test/acceptance/home-page.controller.acceptance.ts b/examples/todo/test/acceptance/home-page.controller.acceptance.ts
new file mode 100644
index 000000000000..03c0d6f1e63e
--- /dev/null
+++ b/examples/todo/test/acceptance/home-page.controller.acceptance.ts
@@ -0,0 +1,28 @@
+// Copyright IBM Corp. 2018. All Rights Reserved.
+// Node module: @loopback/example-shopping
+// This file is licensed under the MIT License.
+// License text available at https://opensource.org/licenses/MIT
+
+import {Client} from '@loopback/testlab';
+import {TodoListApplication} from '../..';
+import {setupApplication} from './test-helper';
+
+describe('HomePageController', () => {
+ let app: TodoListApplication;
+ let client: Client;
+
+ before('setupApplication', async () => {
+ ({app, client} = await setupApplication());
+ });
+
+ after(async () => {
+ await app.stop();
+ });
+
+ it('exposes a default home page', async () => {
+ await client
+ .get('/')
+ .expect(200)
+ .expect('Content-Type', /text\/html/);
+ });
+});
diff --git a/examples/todo/test/acceptance/test-helper.ts b/examples/todo/test/acceptance/test-helper.ts
new file mode 100644
index 000000000000..46f0b1c3b6fe
--- /dev/null
+++ b/examples/todo/test/acceptance/test-helper.ts
@@ -0,0 +1,24 @@
+import {TodoListApplication} from '../..';
+import {
+ createRestAppClient,
+ givenHttpServerConfig,
+ Client,
+} from '@loopback/testlab';
+
+export async function setupApplication(): Promise {
+ const app = new TodoListApplication({
+ rest: givenHttpServerConfig(),
+ });
+
+ await app.boot();
+ await app.start();
+
+ const client = createRestAppClient(app);
+
+ return {app, client};
+}
+
+export interface AppWithClient {
+ app: TodoListApplication;
+ client: Client;
+}