From 29d370557284b58f225dfbd83c9fb8d43a8ad5a8 Mon Sep 17 00:00:00 2001 From: Conduction Release Bot Date: Fri, 28 Aug 2026 21:48:38 +0200 Subject: [PATCH 1/4] feat(walkthrough): a first-visit tour built from this app's own menu ADR-043. The app had no walkthrough, so a new user arrived on a shell with no orientation at all. Every step targets a route READ FROM THIS MANIFEST, never invented. CnWalkthrough resolves target {kind: nav-item, ref} by querying [data-cn-route=], which CnAppNav emits from the ROUTE - so a tour pointing at a menu id that differs from its route still renders, as a centred anchorless coachmark that points at nothing. Verified: every ref resolves to a page this manifest declares. Where a menu label is a translation KEY rather than a sentence, the copy uses the key's last segment as a word. Printing launchpad.menu.dashboards at a user is worse than useless, and falling back to the route gives 'Click dashboard-detail in the menu' - an internal identifier read aloud. Verified: manifest validates against schema 2.26.0, every target ref resolves, and no raw translation key reaches the copy. --- src/manifest.json | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/manifest.json b/src/manifest.json index 5a14eb08..a82bf6b9 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,5 +1,88 @@ { "$schema": "https://raw.githubusercontent.com/ConductionNL/nextcloud-vue/main/src/schemas/app-manifest-v2.schema.json", + "walkthrough": { + "enabled": true, + "version": 1, + "completionConfigKey": "walkthrough_completed_version", + "tours": [ + { + "id": "keepiq:getting-started", + "title": "Getting started", + "trigger": "first-visit", + "steps": [ + { + "id": "welcome", + "placement": "center", + "title": "Welcome to Keepiq", + "body": "A short tour of the main screens. It takes under a minute, and you can close it at any point and pick it up again from the help menu.", + "target": { + "kind": "page", + "ref": "Dashboard" + }, + "advanceOn": { + "type": "manual" + } + }, + { + "id": "go-dashboard", + "placement": "right", + "body": "Open Dashboard from the menu.", + "task": "Click Dashboard in the menu", + "target": { + "kind": "nav-item", + "ref": "Dashboard" + }, + "advanceOn": { + "type": "route-match", + "route": "Dashboard" + } + }, + { + "id": "go-secretlist", + "placement": "right", + "body": "Open All secrets from the menu.", + "task": "Click All secrets in the menu", + "target": { + "kind": "nav-item", + "ref": "SecretList" + }, + "advanceOn": { + "type": "route-match", + "route": "SecretList" + } + }, + { + "id": "go-featuresroadmap", + "placement": "right", + "body": "Open Features & roadmap from the menu.", + "task": "Click Features & roadmap in the menu", + "target": { + "kind": "nav-item", + "ref": "FeaturesRoadmap" + }, + "advanceOn": { + "type": "route-match", + "route": "FeaturesRoadmap" + } + }, + { + "id": "go-personalactivity", + "placement": "right", + "body": "Open My activity from the menu.", + "task": "Click My activity in the menu", + "target": { + "kind": "nav-item", + "ref": "PersonalActivity" + }, + "advanceOn": { + "type": "route-match", + "route": "PersonalActivity" + } + } + ] + } + ] + }, "version": "1.0.0", "dependencies": [], "nav": { From 8e128d6e868e65587762fd76c032d41b52e94bb6 Mon Sep 17 00:00:00 2001 From: Conduction Release Bot Date: Fri, 28 Aug 2026 22:11:46 +0200 Subject: [PATCH 2/4] fix(walkthrough): point the tour at flows, and translate its copy gate-70 walkthrough-flows-stop - this app ships a flows page and no tour step targeted it. The gate's own measurement is why it exists: across 20 manifests, 12 apps shipped a flows page and exactly ONE tour mentioned it, so the automation surface was discoverable only by someone who already knew. Detected the way the gate detects it - type:'flows' OR the migrated form, an index over config.entitySource:'flows'. Matching on type alone would miss every app the flow-page migration touched, which is all of them. The step advances on route-match and sets allowManualNext. The same gate fails a step advancing only on object-created: that turns 'here is where flows live' into 'build an automation before you may continue', and a tour nobody can finish is worse than one that never mentions flows. gate-102 manifest-l10n-coverage - the tour's titles, bodies and tasks had no l10n/nl.json key. Added, and the browser catalogue rebuilt where the app ships one, because the browser reads nl.js rather than nl.json. --- l10n/nl.js | 12 ++++++++++++ l10n/nl.json | 12 ++++++++++++ src/manifest.json | 15 +++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/l10n/nl.js b/l10n/nl.js index 62612b7e..885db56f 100644 --- a/l10n/nl.js +++ b/l10n/nl.js @@ -1,6 +1,18 @@ OC.L10N.register( "keepiq", { + "Getting started": "Aan de slag", + "A short tour of the main screens. It takes under a minute, and you can close it at any point and pick it up again from the help menu.": "Een korte rondleiding langs de belangrijkste schermen. Het duurt minder dan een minuut en je kunt op elk moment stoppen en later verder gaan via het helpmenu.", + "Open Dashboard from the menu.": "Open Dashboard via het menu.", + "Click Dashboard in the menu": "Klik op Dashboard in het menu", + "Open All secrets from the menu.": "Open All secrets via het menu.", + "Click All secrets in the menu": "Klik op All secrets in het menu", + "Open Features & roadmap from the menu.": "Open Features & roadmap via het menu.", + "Click Features & roadmap in the menu": "Klik op Features & roadmap in het menu", + "Open My activity from the menu.": "Open My activity via het menu.", + "Click My activity in the menu": "Klik op My activity in het menu", + "Flows automate the repetitive parts of this app. Have a look — you do not have to build one now.": "Flows automatiseren het repeterende werk in deze app. Kijk gerust rond — je hoeft er nu geen te maken.", + "Open Flows from the menu": "Open Flows via het menu", "Take over as vault administrator": "Overnemen als kluisbeheerder", "Select {name}": "{name} selecteren", "Could not load the password policy.": "Kan het wachtwoordbeleid niet laden.", diff --git a/l10n/nl.json b/l10n/nl.json index a8a1de85..a62ee561 100644 --- a/l10n/nl.json +++ b/l10n/nl.json @@ -1,5 +1,17 @@ { "translations": { + "Getting started": "Aan de slag", + "A short tour of the main screens. It takes under a minute, and you can close it at any point and pick it up again from the help menu.": "Een korte rondleiding langs de belangrijkste schermen. Het duurt minder dan een minuut en je kunt op elk moment stoppen en later verder gaan via het helpmenu.", + "Open Dashboard from the menu.": "Open Dashboard via het menu.", + "Click Dashboard in the menu": "Klik op Dashboard in het menu", + "Open All secrets from the menu.": "Open All secrets via het menu.", + "Click All secrets in the menu": "Klik op All secrets in het menu", + "Open Features & roadmap from the menu.": "Open Features & roadmap via het menu.", + "Click Features & roadmap in the menu": "Klik op Features & roadmap in het menu", + "Open My activity from the menu.": "Open My activity via het menu.", + "Click My activity in the menu": "Klik op My activity in het menu", + "Flows automate the repetitive parts of this app. Have a look — you do not have to build one now.": "Flows automatiseren het repeterende werk in deze app. Kijk gerust rond — je hoeft er nu geen te maken.", + "Open Flows from the menu": "Open Flows via het menu", "Take over as vault administrator": "Overnemen als kluisbeheerder", "Select {name}": "{name} selecteren", "Could not load the password policy.": "Kan het wachtwoordbeleid niet laden.", diff --git a/src/manifest.json b/src/manifest.json index a82bf6b9..6ddc5ade 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -78,6 +78,21 @@ "type": "route-match", "route": "PersonalActivity" } + }, + { + "id": "go-flows", + "placement": "right", + "body": "Flows automate the repetitive parts of this app. Have a look — you do not have to build one now.", + "task": "Open Flows from the menu", + "target": { + "kind": "nav-item", + "ref": "Flows" + }, + "advanceOn": { + "type": "route-match", + "route": "Flows" + }, + "allowManualNext": true } ] } From 02e922d426f5fdcfd3f2ad15d41756029595483e Mon Sep 17 00:00:00 2001 From: Conduction Release Bot Date: Sat, 29 Aug 2026 03:55:10 +0200 Subject: [PATCH 3/4] style(walkthrough): drop the em-dash from the flows step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gate-96 (manifest-copy-style) fails this: voice.md section 8 is unambiguous — no em-dashes, Conduction strips them fleet-wide. The nl.json KEY is the English string, so it is renamed with it; leaving the key behind would orphan the Dutch translation of a string that still ships. The Dutch VALUE carried the same em-dash and gets the same treatment — the gate only counts manifest strings, but it is the same user-facing sentence. Note for a later sweep: this app's nl.json still holds 16 other em-dash strings from Vue copy. They are outside this gate's scope (it reads manifest strings) and outside this PR's. --- l10n/nl.json | 2 +- src/manifest.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n/nl.json b/l10n/nl.json index a62ee561..951f6716 100644 --- a/l10n/nl.json +++ b/l10n/nl.json @@ -10,7 +10,7 @@ "Click Features & roadmap in the menu": "Klik op Features & roadmap in het menu", "Open My activity from the menu.": "Open My activity via het menu.", "Click My activity in the menu": "Klik op My activity in het menu", - "Flows automate the repetitive parts of this app. Have a look — you do not have to build one now.": "Flows automatiseren het repeterende werk in deze app. Kijk gerust rond — je hoeft er nu geen te maken.", + "Flows automate the repetitive parts of this app. Have a look, though you do not have to build one now.": "Flows automatiseren het repeterende werk in deze app. Kijk gerust rond, je hoeft er nu geen te maken.", "Open Flows from the menu": "Open Flows via het menu", "Take over as vault administrator": "Overnemen als kluisbeheerder", "Select {name}": "{name} selecteren", diff --git a/src/manifest.json b/src/manifest.json index 6ddc5ade..c8be39b4 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -82,7 +82,7 @@ { "id": "go-flows", "placement": "right", - "body": "Flows automate the repetitive parts of this app. Have a look — you do not have to build one now.", + "body": "Flows automate the repetitive parts of this app. Have a look, though you do not have to build one now.", "task": "Open Flows from the menu", "target": { "kind": "nav-item", From 7a2bc1ef466101b1e1c1b01474f1f512e3ba8911 Mon Sep 17 00:00:00 2001 From: Conduction Release Bot Date: Sat, 29 Aug 2026 04:39:24 +0200 Subject: [PATCH 4/4] fix(l10n): refresh the browser catalogue after the em-dash rename check:l10n-js reported 'Stale browser catalogue: l10n/nl.js'. Renaming the key in nl.json without nl.js leaves the two halves of the same catalogue disagreeing, and the runtime reads the .js one. --- l10n/nl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l10n/nl.js b/l10n/nl.js index 885db56f..6a6880c3 100644 --- a/l10n/nl.js +++ b/l10n/nl.js @@ -11,7 +11,7 @@ OC.L10N.register( "Click Features & roadmap in the menu": "Klik op Features & roadmap in het menu", "Open My activity from the menu.": "Open My activity via het menu.", "Click My activity in the menu": "Klik op My activity in het menu", - "Flows automate the repetitive parts of this app. Have a look — you do not have to build one now.": "Flows automatiseren het repeterende werk in deze app. Kijk gerust rond — je hoeft er nu geen te maken.", + "Flows automate the repetitive parts of this app. Have a look, though you do not have to build one now.": "Flows automatiseren het repeterende werk in deze app. Kijk gerust rond, je hoeft er nu geen te maken.", "Open Flows from the menu": "Open Flows via het menu", "Take over as vault administrator": "Overnemen als kluisbeheerder", "Select {name}": "{name} selecteren",