diff --git a/deploy/nginx/mailcow-plugin-runtime.conf b/deploy/nginx/mailcow-plugin-runtime.conf
new file mode 100644
index 0000000..82f2ff2
--- /dev/null
+++ b/deploy/nginx/mailcow-plugin-runtime.conf
@@ -0,0 +1 @@
+# Mailcow plugin runtime reverse proxy\n# Include this from the Mailcow nginx site or merge into the active server block.\n# Adjust upstream address if the runtime is not on localhost:4110.\n\nlocation /plugins-runtime/ {\n proxy_pass http://127.0.0.1:4110/;\n proxy_http_version 1.1;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n\n proxy_request_buffering off;\n proxy_buffering off;\n client_max_body_size 100m;\n}\n
\ No newline at end of file
diff --git a/docs/v0.3.0-mailcow-integration.md b/docs/v0.3.0-mailcow-integration.md
new file mode 100644
index 0000000..c386597
--- /dev/null
+++ b/docs/v0.3.0-mailcow-integration.md
@@ -0,0 +1 @@
+# mailcow-plugin-runtime v0.3.0 integration plan\n\n## Scope\n- Proxy runtime behind Mailcow at \n- Load runtime bootstrap into Mailcow UI\n- Render compose toolbar and attachment hooks\n- Wire plugin end to end\n\n## Deployment notes\n1. Start runtime on port .\n2. Add to the Mailcow nginx server block.\n3. Ensure is reachable from Mailcow.\n4. Inject the bootstrap loader into the Mailcow compose page.\n\n## Expected follow-up\n- Replace placeholders in with actual selectors and injection logic.\n- Implement attachment token exchange and ownCloud file listing here.\n
\ No newline at end of file
diff --git a/plugins/owncloud-attach/api/README.md b/plugins/owncloud-attach/api/README.md
new file mode 100644
index 0000000..2562638
--- /dev/null
+++ b/plugins/owncloud-attach/api/README.md
@@ -0,0 +1 @@
+# owncloud-attach API placeholders\n\nExpected endpoints:\n- GET /plugins/owncloud-attach/api/files\n- POST /plugins/owncloud-attach/api/attach\n- GET /plugins/owncloud-attach/api/health\n\nImplement the runtime-side token exchange and ownCloud file listing here.\n
\ No newline at end of file
diff --git a/plugins/owncloud-attach/ui/index.html b/plugins/owncloud-attach/ui/index.html
new file mode 100644
index 0000000..d06ca82
--- /dev/null
+++ b/plugins/owncloud-attach/ui/index.html
@@ -0,0 +1 @@
+\n\n
\n \n \n owncloud-attach\n \n \n \n
\n
owncloud-attach
\n
Placeholder UI for the ownCloud picker modal.
\n \n
\n \n\n
\ No newline at end of file
diff --git a/scripts/next-steps.sh b/scripts/next-steps.sh
new file mode 100755
index 0000000..054c964
--- /dev/null
+++ b/scripts/next-steps.sh
@@ -0,0 +1 @@
+#!/usr/bin/env bash\nset -euo pipefail\n\necho 'Next manual steps:'\necho '1. Wire deploy/nginx/mailcow-plugin-runtime.conf into the Mailcow nginx server block.'\necho '2. Make Mailcow load src/integrations/mailcow/install.ts output on compose pages.'\necho '3. Replace placeholder selectors in src/integrations/mailcow/dom-targets.ts.'\necho '4. Build owncloud-attach picker API and file attachment flow.'\n
\ No newline at end of file
diff --git a/src/hooks/mailcow-hooks.ts b/src/hooks/mailcow-hooks.ts
new file mode 100644
index 0000000..3801512
--- /dev/null
+++ b/src/hooks/mailcow-hooks.ts
@@ -0,0 +1 @@
+import { MAILCOW_SELECTORS } from "../integrations/mailcow/dom-targets";\n\nfunction ensureHookContainer(selector: string, id: string): HTMLElement | null {\n const host = document.querySelector(selector);\n if (!host) return null;\n\n let node = document.getElementById(id);\n if (!node) {\n node = document.createElement("div");\n node.id = id;\n node.dataset.pluginHookContainer = id;\n host.appendChild(node);\n }\n\n return node;\n}\n\nexport function mountComposeToolbarHook(): void {\n ensureHookContainer(MAILCOW_SELECTORS.composeToolbar, "mailcow-plugin-hook-compose-toolbar");\n}\n\nexport function mountComposeAttachmentsHook(): void {\n ensureHookContainer(MAILCOW_SELECTORS.composeAttachments, "mailcow-plugin-hook-compose-attachments");\n}\n
\ No newline at end of file
diff --git a/src/integrations/mailcow/bootstrap-loader.ts b/src/integrations/mailcow/bootstrap-loader.ts
new file mode 100644
index 0000000..7ea1d0f
--- /dev/null
+++ b/src/integrations/mailcow/bootstrap-loader.ts
@@ -0,0 +1 @@
+export interface MailcowBootstrapOptions {\n runtimeBaseUrl?: string;\n}\n\nexport function loadPluginRuntimeBootstrap(options: MailcowBootstrapOptions = {}): HTMLScriptElement {\n const runtimeBaseUrl = options.runtimeBaseUrl ?? "/plugins-runtime";\n const script = document.createElement("script");\n script.src = `\${runtimeBaseUrl}/runtime/bootstrap.js`;\n script.async = true;\n script.dataset.runtimeBaseUrl = runtimeBaseUrl;\n document.head.appendChild(script);\n return script;\n}\n
\ No newline at end of file
diff --git a/src/integrations/mailcow/dom-targets.ts b/src/integrations/mailcow/dom-targets.ts
new file mode 100644
index 0000000..9c67ed6
--- /dev/null
+++ b/src/integrations/mailcow/dom-targets.ts
@@ -0,0 +1 @@
+export const MAILCOW_SELECTORS = {\n composeToolbar: "[data-mailcow-compose-toolbar], .compose-toolbar, .toolbar",\n composeAttachments: "[data-mailcow-compose-attachments], .compose-attachments, .attachments",\n};\n
\ No newline at end of file
diff --git a/src/integrations/mailcow/install.ts b/src/integrations/mailcow/install.ts
new file mode 100644
index 0000000..9ffc33a
--- /dev/null
+++ b/src/integrations/mailcow/install.ts
@@ -0,0 +1 @@
+import { loadPluginRuntimeBootstrap } from "./bootstrap-loader";\nimport { mountComposeToolbarHook, mountComposeAttachmentsHook } from "../hooks/mailcow-hooks";\n\nexport function installMailcowPluginRuntime(): void {\n loadPluginRuntimeBootstrap();\n\n window.addEventListener("DOMContentLoaded", () => {\n mountComposeToolbarHook();\n mountComposeAttachmentsHook();\n });\n}\n
\ No newline at end of file