OpenCloud Web is a TypeScript/Vue 3 single-page application that serves as the browser-based frontend for OpenCloud. It is structured as a pnpm monorepo and uses Vite as the build tool.
/
├── packages/ # All packages and apps (monorepo workspaces)
│ ├── web-client/ # API abstraction layer (LibreGraph, WebDAV, OCS)
│ ├── web-pkg/ # Shared composables, components, types and helpers
│ ├── web-runtime/ # Core: auth, bootstrapping, layout, routing, theming
│ ├── web-test-helpers/ # Unit test helpers (published as @opencloud-eu/web-test-helpers)
│ ├── design-system/ # ODS – design tokens, components, styles
│ ├── eslint-config/ # Shared ESLint configuration
│ ├── prettier-config/ # Shared Prettier configuration
│ ├── tsconfig/ # Shared TypeScript configuration
│ ├── extension-sdk/ # Utilities for custom extensions
│ └── web-app-*/ # Standalone apps/extensions (files, search, preview, …)
├── tests/
│ └── e2e/ # End-to-end tests (Playwright + Cucumber)
├── dev/ # Docker/infrastructure config for local development
├── docker-compose.yml
├── vite.config.ts # Root Vite config
└── package.json # Root scripts and dev dependencies
Each package typically contains:
src/– source codetests/unit/– unit tests (mirroringsrc/folder structure)l10n/– translationspackage.json– package-specific metadata and dependencies
Scripts are defined in the root package.json and run with pnpm:
pnpm build # Production build
pnpm build:w # Build with watch/hot-reload
pnpm vite # Instant hot-reload dev server (faster iteration)
pnpm lint # Run ESLint
pnpm format:check # Check formatting with Prettier
pnpm format:write # Auto-fix formatting with Prettier
pnpm check:types # TypeScript type checking via vue-tsc
pnpm check:all # Types + lint + format + unit tests (run before opening a PR)
pnpm test:unit --run # Run all unit tests with Vitest (--run prevents watch mode)
pnpm test:e2e:cucumber # Run e2e tests (default browser)
Enforced via Prettier (packages/prettier-config). Run pnpm format:write to auto-fix.
Enforced via ESLint (packages/eslint-config). Run pnpm lint to check.
- TypeScript everywhere – use types to catch bugs at compile time and support IDE tooling.
- Composables over services – encapsulate reusable logic in composables. Avoid services.
- Early returns – prefer early returns to keep code readable and performant.
- Translations – use
$gettext(or its variants) for all user-facing strings. Don't manually edit the generatedl10n/translations.jsonfiles inside a package. - Minimal dependencies – avoid adding new dependencies unless necessary, to keep bundle size small and reduce security surface.
- Vue unref() vs .value – prefer
unref()for accessing Ref values for better readability. Use.valueonly when setting values (e.g.foo.value = 'bar'orfoo.value.push('bar')). - Functions vs arrow functions – prefer named
functiondeclarations over arrow functions. Use arrow functions only for callbacks or when thethiscontext requires it. - Tailwind CSS – use Tailwind utility classes for styling. Avoid custom CSS unless necessary.
- Cross-package imports – only
web-pkg,web-client,web-test-helpers, anddesign-systemmay be imported from other packages. Always use their package names (e.g.import { useFoo } from '@opencloud-eu/web-pkg'), never relative paths. Check each package'sexportsfield inpackage.jsonto see what is exposed.
- Composition API +
<script setup>– prefer Vue's Composition API with<script setup>over the Options API. - Component size – keep components under ~300 lines. Split larger ones into smaller sub-components.
- Props – define props with explicit types and default values. Avoid using
anyorunknown. - Emits – define emitted events with explicit types.
- Framework: Vitest
- Location:
tests/unit/inside each package, mirroring thesrc/folder structure. - File naming:
{originalFileName}.spec.ts(e.g.src/composables/foo.ts→tests/unit/composables/foo.spec.ts). - Helpers: The
@opencloud-eu/web-test-helperspackage (packages/web-test-helpers) provides shared utilities for mounting components, mocking stores, etc. Use it instead of rolling your own helpers. - Snapshots: Avoid using snapshot tests, as they can be brittle and hard to maintain. Prefer explicit assertions that check specific behavior or output.
- Run:
pnpm test:unit --run(the--runflag is required to prevent Vitest from staying in watch mode) - Run single file:
pnpm test:unit --run packages/path/to/file.spec.ts
- Framework: Playwright + Cucumber
- Location:
tests/e2e/(outside ofpackages/) - Prerequisites: Run
pnpm buildbefore executing e2e tests. A running OpenCloud backend is also required — usedocker-compose up -dto start one locally. - Run:
pnpm test:e2e:cucumber
Full developer documentation is available at https://docs.opencloud.eu/docs/dev/web/.