Back to list
Building a Nextcloud application
Published
Long

Building a Nextcloud application

This page summarizes my experience around the development of an application for Nextcloud: the search page.

As far as I was able to understand, Nextcloud application front-ends are mostly written with Vue 2.

I decided not to.

I decided to go with Svelte.

The first version of the application consist simply in a PHP controller and a front-end application that uses Nextcloud's public API.

Development environment setup

Before anything, start with the Nextcloud app development tutorials!

These are the steps to follow (all are described in the tutorials):

  1. Install docker and docker-compose on your development machine
  2. Install local a Nextcloud server with Nextcloud dev server -- very well explained steps: a. download the b. run the boostrap.sh to configure everything c. start the server in it simplest form docker-compose up nextcloud proxy There are other services described in the docker-compose.yml file but I didn't need them
  3. Install the template app inside the server. If your dev server code is in ~/src/nextcloud-docker-dev the code of your application shoul reside in ~/src/nextcloud-docker-dev/workspace/server/apps-extra/<APPLICATION_NAME>. The name of the folder must match what is declared in the appinf/info.xml id tag.

I don't like to have to work in a folder inside the local Nextcloud instance (/workspace/server/apps-extras) but it is needed if you need for multiple reasons. It also brings some issues to the frontend project configuration if you plan to not use the default eslint (Vue based) provided by Nextcloud (see below).

ESLint Specific configurations

As I didn't use the rules or profiles defined by Nextcloud for eslint. I had to add root: true to my application esling configuration file in order for it to work. Else it will complain about missing Vue related eslint packages that I did not install.

Svelte in Nextcloud

For this project, I used [Svelte] so I trashed the Vue example files and various configuration replacing them with the one of a fresh svelte app.

I had to customize Vite in order to include the CSS inside the JS build as I wasn't able to make it comply with how Nextcloud expects the files to be: JS in js folder and the CSS in the css folder of the application.

I used vite-plugin-css-injected-by-js to do that.

vite.config.ts

import { svelte } from "@sveltejs/vite-plugin-svelte";
import { defineConfig } from "vite";
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";

// https://vitejs.dev/config/
export default defineConfig((config) => {
const devMode = config.mode === "dev";

return {
...config,
plugins: [svelte(), cssInjectedByJsPlugin()],

build: {
sourcemap: devMode,
minify: !devMode,
outDir: "js",
lib: {
formats: ["iife"],
entry: "src/main.ts",
name: "main",
},
},
};
});

For the svelte configuration, nothing fancy

import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";

export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
};

The script section in the package.json:

...
  "scripts": {
    "dev": "vite build --mode dev",
    "build": "vite build",
    "preview": "vite preview",
    "check": "svelte-check --tsconfig ./tsconfig.json",
    "lint": "eslint --config .eslintrc.cjs src/**/*.ts src/**/*.svelte"
  },
...

All the files are available on the project's repo on github.

There is no automated rebuild, no live reload. This is my current trick, saved as a file in the bin folder.

find src template | entr npm run build 

You still have to reload the page in the nextcloud instance as there's no live reload mechanism.

Nextcloud API

Nextcloud provides several front-end packages.

The following package are used in my application:

DISCLAIMER: the search page application does not need (yet) to interact with proviledged API. Those API might require the user (admin) to confirm his password to obtain a refreshed admin token.

Currently there are 2 ways to do that:

  1. Using @nextcloud/request-password but this requires the application toa be built including Vue2. It works but is quite heavy: over 500 kB as I don't use Vue for the rest of the application
  2. Calling OC javascript equivalent API, but that is not supported.

This is a major issue for future developments of the application to integrate an admin settings page, locking on on front-end technology does not sound good for nobody. For the developers it might become deprecated and less exciting to work with. For the platform perspective, making evolution very difficult.

I would expect the Nextcloud team to provide a better solution for this as forcing the application development to happen on Vue 2 is not future proof but the Vue2 modules seems to be the path chosen by the Nextcloud echo-system maintainers. Too bad...

Releasing

Again, following the documentation,

  1. Create a PR for the application certificat sign request to obtain a certificate that will be used to verify the package You first need to obtain a certificate to be able to sign your application package. There is a repository to request the certificate. This has to be done once per application as far as I can understand.
  2. Build the application package make appstore
  3. Signing and uploading the package

Release automation

The documentation is quite detailed.

But I had a hard time to make it work. Check the result in the .github folder in the repository.

I ended implementing 2 workflows, one for pre-releases and a second for production releases. Those releases are just piloted by git tags.

I have not yet been able to have the PHP unit test to succeed :-(

Conclusion

Globally the experience was good, there is a lot of documentation available but it sometimes gets difficult to find the correct version. And some do not provide enough details. I'll dig into the settings part in a future post.

Regarding front-end development, I was mixed feelings. In addition to the Vue 2 "issue", I have the feeling that some basic things are not well explained. Everything seem straightforward if the application only interacts with its own backend but interacting with the core is a little bit more obscure and requires you to dig into the existing code repositories to understand how others are doing it.