AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Nextcloud Impl App Development

skill-impertio-studio-nextcloud-claude-skill-package-nextcloud-impl-app-development · by Impertio-Studio

>

No reviews yet
0 installs
14 views
0.0% view→install

Install

$ agentstack add skill-impertio-studio-nextcloud-claude-skill-package-nextcloud-impl-app-development

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-impertio-studio-nextcloud-claude-skill-package-nextcloud-impl-app-development)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Nextcloud Impl App Development? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

nextcloud-impl-app-development

Quick Reference

Full-Stack App Layer Map

| Layer | PHP (Backend) | Vue.js (Frontend) | |-------|--------------|-------------------| | Entry point | lib/AppInfo/Application.php | src/main.js | | Routing | appinfo/routes.php | @nextcloud/router | | Controllers | lib/Controller/*.php | N/A | | Services | lib/Service/*.php | src/services/*.js | | Data access | lib/Db/Entity.php + Mapper.php | @nextcloud/axios | | State bridge | IInitialState::provideInitialState() | loadState() | | UI components | N/A | @nextcloud/vue | | Notifications | N/A | @nextcloud/dialogs |

Development Commands

| Command | Purpose | |---------|---------| | npm run dev | Build frontend for development | | npm run build | Build frontend for production | | npm run watch | Rebuild on file changes | | npm run serve | Dev server with HMR | | php occ app:enable myapp | Enable the app | | php occ app:disable myapp | Disable the app | | php occ migrations:migrate myapp | Run database migrations |

Critical Warnings

ALWAYS set ` in appinfo/info.xml` -- auto-wiring and autoloading depend on it.

ALWAYS use @nextcloud/axios for HTTP requests -- it handles CSRF tokens and authentication automatically.

ALWAYS use provideInitialState() in PHP and loadState() in JS for server-to-client data -- NEVER inject data via inline scripts or global variables.

ALWAYS use CSS custom properties (--color-*) for colors -- NEVER hardcode colors (breaks dark mode and theming).

ALWAYS use direct component imports (@nextcloud/vue/components/NcButton) -- barrel imports increase bundle size.

NEVER use \OCP\Server::get() for service resolution -- use constructor injection for testability.

NEVER use OCP\ILogger -- deprecated since NC 24. Use Psr\Log\LoggerInterface.

NEVER use raw fetch() or plain axios -- use @nextcloud/axios which handles auth headers automatically.

NEVER call loadState() without a fallback for optional data -- it throws on missing keys.

NEVER modify existing migration files -- create new migrations for schema changes.


Decision Tree: Route Type Selection

Is this endpoint consumed by external clients or other apps?
├── YES: Will responses need the OCS JSON/XML envelope?
│   ├── YES → Use OCS route + OCSController
│   │   Route: 'ocs' => [['name' => 'api#method', 'url' => '/api/v1/...']]
│   └── NO → Use regular route + ApiController (adds CORS)
│       Route: 'routes' => [['name' => 'api#method', 'url' => '/api/...']]
└── NO: Internal app use only
    ├── Page rendering? → Use Controller + TemplateResponse
    │   Route: 'routes' => [['name' => 'page#index', 'url' => '/']]
    ├── CRUD resource? → Use resource routes
    │   Route: 'resources' => ['item' => ['url' => '/items']]
    └── AJAX from Vue frontend? → Use regular route + JSONResponse
        Route: 'routes' => [['name' => 'item#create', 'url' => '/items']]

Essential Patterns

Pattern 1: Full-Stack App Creation (Step-by-Step)

Step 1: App manifest (appinfo/info.xml)


    taskboard
    Task Board
    Simple task management
    A task board for managing project tasks
    1.0.0
    AGPL-3.0-or-later
    Developer Name
    TaskBoard
    organization
    
        
    
    
        
            Task Board
            taskboard.page.index
            app.svg
        
    

Step 2: Application bootstrap (lib/AppInfo/Application.php)

 [
        ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
    ],
    'ocs' => [
        ['name' => 'task_api#index', 'url' => '/api/v1/tasks', 'verb' => 'GET'],
        ['name' => 'task_api#show', 'url' => '/api/v1/tasks/{id}', 'verb' => 'GET'],
        ['name' => 'task_api#create', 'url' => '/api/v1/tasks', 'verb' => 'POST'],
        ['name' => 'task_api#update', 'url' => '/api/v1/tasks/{id}', 'verb' => 'PUT'],
        ['name' => 'task_api#destroy', 'url' => '/api/v1/tasks/{id}', 'verb' => 'DELETE'],
    ],
];

Step 4-8: See [references/examples.md](references/examples.md) for the complete Entity, Mapper, Service, Controller, and Vue.js implementation.

Pattern 2: Initial State Bridge (PHP to JavaScript)

PHP side -- provide data in controller:

use OCP\AppFramework\Services\IInitialState;

class PageController extends Controller {
    public function __construct(
        string $appName,
        IRequest $request,
        private IInitialState $initialState,
        private TaskService $service,
        private ?string $userId,
    ) {
        parent::__construct($appName, $request);
    }

    #[NoAdminRequired]
    #[NoCSRFRequired]
    public function index(): TemplateResponse {
        // Eager: always serialized
        $this->initialState->provideInitialState(
            'tasks',
            $this->service->findAll($this->userId)
        );

        // Lazy: only serialized when loaded by frontend
        $this->initialState->provideLazyInitialState(
            'config',
            fn () => $this->service->getConfig()
        );

        return new TemplateResponse('taskboard', 'main');
    }
}

JavaScript side -- consume data:

import { loadState } from '@nextcloud/initial-state'

// ALWAYS provide fallback for optional data
const tasks = loadState('taskboard', 'tasks', [])
const config = loadState('taskboard', 'config', { maxTasks: 100 })

Pattern 3: Frontend API Service Layer

// src/services/TaskService.js
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'

const baseUrl = generateOcsUrl('/apps/taskboard/api/v1')

export async function fetchTasks() {
    const response = await axios.get(`${baseUrl}/tasks`)
    return response.data.ocs.data
}

export async function createTask(title, description) {
    const response = await axios.post(`${baseUrl}/tasks`, { title, description })
    return response.data.ocs.data
}

export async function updateTask(id, data) {
    const response = await axios.put(`${baseUrl}/tasks/${id}`, data)
    return response.data.ocs.data
}

export async function deleteTask(id) {
    await axios.delete(`${baseUrl}/tasks/${id}`)
}

Pattern 4: Vue.js App Entry Point

// src/main.js
import Vue from 'vue'
import App from './App.vue'

const appElement = document.getElementById('content')
new Vue({
    el: appElement,
    render: h => h(App),
})

Pattern 5: Vue Component with Nextcloud UI


    
        
            
        
        
            
            
            
                {{ selectedTask.title }}
                {{ selectedTask.description }}
            
        
    

import NcContent from '@nextcloud/vue/components/NcContent'
import NcAppContent from '@nextcloud/vue/components/NcAppContent'
import NcAppNavigation from '@nextcloud/vue/components/NcAppNavigation'
import NcAppNavigationItem from '@nextcloud/vue/components/NcAppNavigationItem'
import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
import { loadState } from '@nextcloud/initial-state'
import { showSuccess, showError } from '@nextcloud/dialogs'
import '@nextcloud/dialogs/style.css'
import { fetchTasks, deleteTask } from './services/TaskService'

export default {
    name: 'App',
    components: {
        NcContent,
        NcAppContent,
        NcAppNavigation,
        NcAppNavigationItem,
        NcEmptyContent,
    },
    data() {
        return {
            tasks: loadState('taskboard', 'tasks', []),
            selectedTask: null,
        }
    },
    methods: {
        selectTask(task) {
            this.selectedTask = task
        },
    },
}

.task-detail {
    padding: 20px;
    color: var(--color-main-text);
}

Pattern 6: Webpack Configuration

// webpack.config.js
const webpackConfig = require('@nextcloud/webpack-vue-config')
module.exports = webpackConfig
// package.json (relevant sections)
{
    "scripts": {
        "build": "webpack --node-env production --progress",
        "dev": "webpack --node-env development --progress",
        "watch": "webpack --node-env development --progress --watch",
        "serve": "webpack --node-env development serve --progress"
    },
    "dependencies": {
        "@nextcloud/axios": "^2.0.0",
        "@nextcloud/dialogs": "^5.0.0",
        "@nextcloud/initial-state": "^2.0.0",
        "@nextcloud/router": "^3.0.0",
        "@nextcloud/vue": "^8.0.0",
        "vue": "^2.7.0"
    },
    "devDependencies": {
        "@nextcloud/webpack-vue-config": "^6.0.0"
    }
}

Development Lifecycle

New App Checklist

  1. Scaffold -- Use https://apps.nextcloud.com/developer/apps/generate or create manually
  2. Configure -- Set info.xml with correct `, , `
  3. Backend -- Create Entity, Mapper, Service, Controller chain
  4. Database -- Create migration in lib/Migration/
  5. Routes -- Define in appinfo/routes.php
  6. Frontend -- Set up src/main.js, App.vue, webpack config
  7. Bridge -- Connect PHP and JS via IInitialState / loadState()
  8. Build -- Run npm install && npm run build
  9. Enable -- Run php occ app:enable myapp
  10. Test -- Verify in browser, check browser console and Nextcloud log

File Naming Conventions

| Layer | Convention | Example | |-------|-----------|---------| | Entity | Singular PascalCase | lib/Db/Task.php | | Mapper | Entity + Mapper | lib/Db/TaskMapper.php | | Service | Entity + Service | lib/Service/TaskService.php | | Controller | Entity + Controller or ApiController | lib/Controller/TaskApiController.php | | Migration | Version{MMDD}Date{timestamp} | lib/Migration/Version1000Date20240101000000.php | | Vue component | PascalCase .vue | src/components/TaskItem.vue | | JS service | PascalCase .js | src/services/TaskService.js |


Reference Links

  • [references/methods.md](references/methods.md) -- Full-stack development patterns and API reference
  • [references/examples.md](references/examples.md) -- Complete app example: Entity, Mapper, Service, Controller, Vue.js
  • [references/anti-patterns.md](references/anti-patterns.md) -- Development workflow mistakes

Official Sources

  • https://docs.nextcloud.com/server/latest/developermanual/appdevelopment/intro.html
  • https://docs.nextcloud.com/server/latest/developermanual/appdevelopment/bootstrap.html
  • https://docs.nextcloud.com/server/latest/developermanual/diggingdeeper/controllers.html
  • https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html
  • https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html
  • https://github.com/nextcloud-libraries/nextcloud-vue

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.