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):
- Install docker and docker-compose on your development machine
- 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 formdocker-compose up nextcloud proxy
There are other services described in the docker-compose.yml file but I didn't need them - 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 theappinf/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:
- @nextcloud/router provides tools to build the urls to reach Nextcloud's APIs.
- @nextcloud/axios provides an axios custom for Nextcloud's API in order to add all the required headers.
- @nextcloud/l10n provides the methods to handle your application translations. Although you can use
window.t
, little by little, the feature provided onwindow
will disappear in favor of the @nextcloud modules.
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:
- 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
- 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,
- 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.
- Build the application package
make appstore
- 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.