How to Write an ownCloud App with the New ownCloud Vue.js Frontend Phoenix

Frontend development does not have to be hard – with the right framework. Phoenix, the new ownCloud frontend, makes it easy to develop extensions for ownCloud. This guide explains how you can get started.

Since Phoenix was announced in March 2018, little new information has surfaced. We mostly worked in silence. Now Phoenix is far enough that you can start extending it with apps – time to show what you can do with the new frontend with a simple example app.

We already built a small Markdown Editor and a simple PDF Viewer for Phoenix. The PDF Viewer extension is a good example to show what a Phoenix app needs and how you can use the framework.

Get Started With Developing!

Intrigued? Grab a cup of coffee and sit down. Developing a small app for Phoenix is not hard if you know the basics of JavaScript – you can pick up VueJS along the way, if you don’t know it already (for those who don’t, see here why Vue.js is awesome)

You can try out the current state of Phoenix and the two apps at (username: demo, passphrase: demo), our preview instance. It always shows the most recent development progress.

1. How to Load a Phoenix App?

Phoenix has a json config file to configure the list of apps which are to be loaded. For testing, enter your app manually, later the Market app will handle this

A Phoenix app is basically a webpack bundle living in the folder /apps/${appname}. Phoenix is loading the json config within it’s bootstrap process and loads all of these bundles.

2. Bootstrapping an App

The App Info Structure

A Phoenix extension exposes all its capabilities and properties via an app info structure – though not the info.xml you maybe already know from ownCloud extension development, which is for Marketplace information. In the PDF Viewer app, it looks like this:

const appInfo = {
  name: 'PDF Viewer',
  id: 'pdf-viewer',
  icon: 'ocft icon-application-pdf',
  isFileEditor: true,
  extensions: [{
    extension: 'pdf'

You can use those items for your app like this:

  • name: the human readable and also translated name of the application. currently unused
  • id: the technical identifier which matches up with the app folder name and the name of the webpack bundle
  • icon: this is the icon of the application. currently unused
  • isFileEditor: if this is true this app will appear in the file open dialog
  • extensions: the file extensions your app will offer to open
ownCloud Phoenix open pdf

The UI schema for opening a file with the PDF Viewer

Registering Routes for the App

In addition to the app info structure there is a routes structure which registers frontend routes to the central Phoenix router:

const routes = [{
  path: `/pdf-viewer`,
  component: PdfViewer,
  name: 'pdf-viewer'

The routes follow the structure of the vue-router. You can use these routes to call the application and display your user interface.

There are more settings, but let’s keep this simple and focus on how to implement a viewer application like the PDF viewer:

3. What Happens When an App Opens a File?

A file sync & share solution wants to interact with files, of course. Your app will want to do it, too. So here a small summary how your code can handle files:

When a user opens a file, they see a dialog with all apps which are able to handle the file, e.g. the PDF Viewer if it’s a pdf. The Phoenix files app then navigates to a URL which is to be named just like the app id.

So in case of your PDF Viewer example the route was named pdf-viewer. The route loads the vue component PdfViewer, which loads the file content with the mounted method of the component. Here you can insert your logic.

The file which is supposed to be opened in the viewer is stored in the central vuex store – this is currently a bit cryptic and is likely subject of change as we move on.

ownCloud Phoenix PDF Viewer app

The PDF Viewer app opens the document in a browser tab

4. How to Load File Content in an App?

We are developing a JavaScript client to interact with ownCloud, js-owncloud-client, which was started in 2017 as a Google Summer of Code project. The client is available to all phoenix components via this.$client.

To get the URL for downloading the file, we use a method of the client: const url = this.$client.files.getFileUrl(this.filePath)

As time of writing, js-owncloud-client is not yet transformed to the fetch API. For now, the fetch operations are implemented in the PdfViewer component itself. In future versions of Phoenix and the js-owncloud-client, this will no longer be necessary.

5. Bonus: Display Notifications

Apps usually want to display notifications to the user in case of error, warning or longer running operations ….. a simple helper can be used to show such notifications: The showNotifications method is implemented as getter on the vuex store:

 error (error) {
    title: this.$gettext('PDF could not be loaded ....'),
    desc: error,
    type: 'error'

You can use mapGetters to make it available – call it anywhere in the component. You can use the three items for the following:

  • title: the title of the notification
  • desc: some more detailed description of the notification
  • type: either success, info, warning, or error, the type influences the color of the notification

6. How to Build This Stuff Together?

We use webpack to compile all necessary assets together into one bundle. The webpack config is rather simple – again, the PDF Viewer can be used as example for how a webpack.common.js could look like.

Questions? Get in Touch With Us!

Phoenix is under active development and will be subject to changes. There will be a lot of work on new UIKit components to make Phoenix look better, for example. If you want to look into UI design, take a look at the ownCloud Design System.

If you want to develop your own app for Phoenix, make your ownCloud app compatible with Phoenix, or want to join the development of Phoenix itself, join our RocketChat channel. This is the best place to ask a quick question:

Join #phoenix on!

Did you like this article? Share it with others or leave a comment below:

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.