@taskmark/ui 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/README.md +46 -10
  2. package/app/api/taskmark-reload/route.ts +103 -0
  3. package/app/board/page.tsx +6 -4
  4. package/app/layout.tsx +2 -0
  5. package/app/setup/page.tsx +4 -1
  6. package/bin/lib/resolve-board.mjs +50 -1
  7. package/bin/lib/watch-board-markdown.mjs +65 -0
  8. package/bin/taskmark.js +310 -67
  9. package/components/board/app-bar.tsx +31 -34
  10. package/components/board/board-dev-reloader.tsx +49 -0
  11. package/components/board/epic-list.tsx +2 -4
  12. package/components/board/overall-work-items-list.tsx +2 -1
  13. package/components/board/static-board-app.tsx +0 -1
  14. package/components/board/story-list.tsx +2 -1
  15. package/components/board/task-list.tsx +2 -1
  16. package/components/board/work-item-sheet.tsx +15 -2
  17. package/components/board/work-items-list.tsx +2 -2
  18. package/components/setup/setup-wizard.tsx +2 -6
  19. package/dist/prod-next/BUILD_ID +1 -0
  20. package/dist/{standalone/.next → prod-next}/app-path-routes-manifest.json +3 -2
  21. package/dist/{standalone/.next → prod-next}/build-manifest.json +3 -3
  22. package/dist/prod-next/export-marker.json +6 -0
  23. package/dist/prod-next/images-manifest.json +68 -0
  24. package/dist/prod-next/next-minimal-server.js.nft.json +1 -0
  25. package/dist/prod-next/next-server.js.nft.json +1 -0
  26. package/dist/{standalone/.next → prod-next}/prerender-manifest.json +27 -3
  27. package/dist/{standalone/.next → prod-next}/react-loadable-manifest.json +2 -2
  28. package/dist/prod-next/required-server-files.js +337 -0
  29. package/dist/{standalone/.next → prod-next}/required-server-files.json +0 -7
  30. package/dist/{standalone/.next → prod-next}/routes-manifest.json +6 -0
  31. package/dist/prod-next/server/app/_global-error/page.js +32 -0
  32. package/dist/prod-next/server/app/_global-error/page.js.nft.json +1 -0
  33. package/dist/prod-next/server/app/_global-error/page_client-reference-manifest.js +1 -0
  34. package/dist/{standalone/.next → prod-next}/server/app/_global-error.html +1 -1
  35. package/dist/{standalone/.next → prod-next}/server/app/_global-error.rsc +1 -1
  36. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_full.segment.rsc +1 -1
  37. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  38. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  39. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_head.segment.rsc +1 -1
  40. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_index.segment.rsc +1 -1
  41. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  42. package/dist/prod-next/server/app/_not-found/page.js +2 -0
  43. package/dist/prod-next/server/app/_not-found/page.js.nft.json +1 -0
  44. package/dist/prod-next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  45. package/dist/prod-next/server/app/_not-found.html +1 -0
  46. package/dist/prod-next/server/app/_not-found.rsc +21 -0
  47. package/dist/prod-next/server/app/_not-found.segments/_full.segment.rsc +21 -0
  48. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_head.segment.rsc +1 -1
  49. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_index.segment.rsc +5 -4
  50. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  51. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  52. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  53. package/dist/prod-next/server/app/api/taskmark-reload/route.js +1 -0
  54. package/dist/prod-next/server/app/api/taskmark-reload/route.js.nft.json +1 -0
  55. package/dist/prod-next/server/app/api/taskmark-reload/route_client-reference-manifest.js +1 -0
  56. package/dist/{standalone/.next → prod-next}/server/app/board/page.js +14 -14
  57. package/dist/prod-next/server/app/board/page.js.nft.json +1 -0
  58. package/dist/prod-next/server/app/board/page_client-reference-manifest.js +1 -0
  59. package/dist/{standalone/.next → prod-next}/server/app/favicon.ico/route.js +1 -1
  60. package/dist/prod-next/server/app/favicon.ico/route.js.nft.json +1 -0
  61. package/dist/prod-next/server/app/page.js +2 -0
  62. package/dist/prod-next/server/app/page.js.nft.json +1 -0
  63. package/dist/prod-next/server/app/page_client-reference-manifest.js +1 -0
  64. package/dist/prod-next/server/app/setup/page.js +2 -0
  65. package/dist/prod-next/server/app/setup/page.js.nft.json +1 -0
  66. package/dist/prod-next/server/app/setup/page_client-reference-manifest.js +1 -0
  67. package/dist/prod-next/server/app/setup.html +1 -0
  68. package/dist/prod-next/server/app/setup.meta +17 -0
  69. package/dist/{standalone/.next/server/app/_not-found.rsc → prod-next/server/app/setup.rsc} +17 -15
  70. package/dist/{standalone/.next/server/app/_not-found.segments → prod-next/server/app/setup.segments}/_full.segment.rsc +17 -15
  71. package/dist/prod-next/server/app/setup.segments/_head.segment.rsc +6 -0
  72. package/dist/prod-next/server/app/setup.segments/_index.segment.rsc +8 -0
  73. package/dist/prod-next/server/app/setup.segments/_tree.segment.rsc +5 -0
  74. package/dist/prod-next/server/app/setup.segments/setup/__PAGE__.segment.rsc +6 -0
  75. package/dist/prod-next/server/app/setup.segments/setup.segment.rsc +5 -0
  76. package/dist/{standalone/.next → prod-next}/server/app-paths-manifest.json +3 -2
  77. package/dist/{standalone/.next → prod-next}/server/chunks/319.js +1 -1
  78. package/dist/{standalone/.next → prod-next}/server/chunks/490.js +2 -2
  79. package/dist/prod-next/server/chunks/57.js +19 -0
  80. package/dist/prod-next/server/chunks/616.js +1 -0
  81. package/dist/prod-next/server/chunks/708.js +1 -0
  82. package/dist/prod-next/server/chunks/724.js +1 -0
  83. package/dist/{standalone/.next/server/chunks/445.js → prod-next/server/chunks/741.js} +2 -2
  84. package/dist/prod-next/server/functions-config-manifest.json +6 -0
  85. package/dist/prod-next/server/interception-route-rewrite-manifest.js +1 -0
  86. package/dist/{standalone/.next → prod-next}/server/middleware-build-manifest.js +1 -1
  87. package/dist/prod-next/server/middleware-react-loadable-manifest.js +1 -0
  88. package/dist/prod-next/server/pages/404.html +1 -0
  89. package/dist/{standalone/.next → prod-next}/server/pages/500.html +1 -1
  90. package/dist/prod-next/server/server-reference-manifest.js +1 -0
  91. package/dist/prod-next/server/server-reference-manifest.json +1 -0
  92. package/dist/prod-next/static/chunks/51.e9139a9ea6eb36b9.js +1 -0
  93. package/dist/{standalone/.next/static/chunks/781-f9f201ddc8c8591a.js → prod-next/static/chunks/613-6f794154d28bb75a.js} +1 -1
  94. package/dist/prod-next/static/chunks/app/_global-error/page-d34451c04262dd7d.js +1 -0
  95. package/dist/prod-next/static/chunks/app/api/taskmark-reload/route-d34451c04262dd7d.js +1 -0
  96. package/dist/prod-next/static/chunks/app/board/page-cd1d9be0c0127225.js +1 -0
  97. package/dist/prod-next/static/chunks/app/layout-856e8a282e69e7d0.js +1 -0
  98. package/dist/prod-next/static/chunks/app/page-d34451c04262dd7d.js +1 -0
  99. package/dist/prod-next/static/chunks/app/setup/page-c3003359e8becc84.js +1 -0
  100. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/app-error-d34451c04262dd7d.js +1 -0
  101. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/forbidden-d34451c04262dd7d.js +1 -0
  102. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/not-found-d34451c04262dd7d.js +1 -0
  103. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/unauthorized-d34451c04262dd7d.js +1 -0
  104. package/dist/{standalone/.next/static/chunks/webpack-b59eaf276b7fb38f.js → prod-next/static/chunks/webpack-bfe8992962004e2b.js} +1 -1
  105. package/dist/prod-next/static/sAWr5ATVuqk6Wqs18kAWs/_buildManifest.js +1 -0
  106. package/dist/public/taskmark-snapshot.json +1 -0
  107. package/lib/display-path.ts +6 -0
  108. package/lib/taskmark/autoconfig.ts +54 -3
  109. package/lib/taskmark/dev-reload-token.ts +5 -0
  110. package/lib/taskmark/discover.ts +2 -1
  111. package/lib/taskmark/project-label.ts +3 -2
  112. package/lib/taskmark/validate.ts +4 -4
  113. package/lib/taskmark/workspace-mode.ts +24 -0
  114. package/lib/taskmark/workspace.ts +5 -2
  115. package/next.config.ts +3 -8
  116. package/package.json +7 -4
  117. package/public/taskmark-snapshot.json +1 -1
  118. package/scripts/build-static.mjs +10 -1
  119. package/scripts/prepare-standalone.mjs +53 -20
  120. package/dist/standalone/.next/BUILD_ID +0 -1
  121. package/dist/standalone/.next/server/app/_global-error/page.js +0 -32
  122. package/dist/standalone/.next/server/app/_global-error/page.js.nft.json +0 -1
  123. package/dist/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +0 -1
  124. package/dist/standalone/.next/server/app/_not-found/page.js +0 -2
  125. package/dist/standalone/.next/server/app/_not-found/page.js.nft.json +0 -1
  126. package/dist/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  127. package/dist/standalone/.next/server/app/_not-found.html +0 -1
  128. package/dist/standalone/.next/server/app/board/page.js.nft.json +0 -1
  129. package/dist/standalone/.next/server/app/board/page_client-reference-manifest.js +0 -1
  130. package/dist/standalone/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  131. package/dist/standalone/.next/server/app/page.js +0 -2
  132. package/dist/standalone/.next/server/app/page.js.nft.json +0 -1
  133. package/dist/standalone/.next/server/app/page_client-reference-manifest.js +0 -1
  134. package/dist/standalone/.next/server/app/setup/page.js +0 -2
  135. package/dist/standalone/.next/server/app/setup/page.js.nft.json +0 -1
  136. package/dist/standalone/.next/server/app/setup/page_client-reference-manifest.js +0 -1
  137. package/dist/standalone/.next/server/chunks/164.js +0 -1
  138. package/dist/standalone/.next/server/chunks/57.js +0 -19
  139. package/dist/standalone/.next/server/chunks/570.js +0 -1
  140. package/dist/standalone/.next/server/chunks/666.js +0 -1
  141. package/dist/standalone/.next/server/functions-config-manifest.json +0 -4
  142. package/dist/standalone/.next/server/middleware-react-loadable-manifest.js +0 -1
  143. package/dist/standalone/.next/server/pages/404.html +0 -1
  144. package/dist/standalone/.next/server/server-reference-manifest.js +0 -1
  145. package/dist/standalone/.next/server/server-reference-manifest.json +0 -1
  146. package/dist/standalone/.next/static/chunks/211.a43663747d668728.js +0 -1
  147. package/dist/standalone/.next/static/chunks/app/_global-error/page-82d456ade9f47021.js +0 -1
  148. package/dist/standalone/.next/static/chunks/app/board/page-6db8dec814516c28.js +0 -1
  149. package/dist/standalone/.next/static/chunks/app/layout-3745e06d87691845.js +0 -1
  150. package/dist/standalone/.next/static/chunks/app/page-82d456ade9f47021.js +0 -1
  151. package/dist/standalone/.next/static/chunks/app/setup/page-8a54c6f26633bdca.js +0 -1
  152. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-82d456ade9f47021.js +0 -1
  153. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-82d456ade9f47021.js +0 -1
  154. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-82d456ade9f47021.js +0 -1
  155. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-82d456ade9f47021.js +0 -1
  156. package/dist/standalone/.next/static/jm3kxf8c6qGe0cYKCktaO/_buildManifest.js +0 -1
  157. package/dist/standalone/node_modules/next/dist/compiled/jest-worker/processChild.js +0 -1
  158. package/dist/standalone/node_modules/next/dist/compiled/jest-worker/threadChild.js +0 -1
  159. package/dist/standalone/node_modules/next/dist/server/lib/start-server.js +0 -494
  160. package/dist/standalone/node_modules/next/dist/server/next-server.js +0 -1429
  161. package/dist/standalone/node_modules/next/dist/server/next.js +0 -455
  162. package/dist/standalone/node_modules/next/dist/server/require-hook.js +0 -82
  163. package/dist/standalone/node_modules/next/dist/server/route-modules/app-page/module.compiled.js +0 -36
  164. package/dist/standalone/node_modules/next/dist/server/route-modules/pages/module.compiled.js +0 -20
  165. package/dist/standalone/node_modules/styled-jsx/index.js +0 -1
  166. package/dist/standalone/node_modules/styled-jsx/package.json +0 -132
  167. package/dist/standalone/node_modules/styled-jsx/style.js +0 -1
  168. package/dist/standalone/package.json +0 -77
  169. package/dist/standalone/public/taskmark-snapshot.json +0 -1
  170. package/dist/standalone/server.js +0 -44
  171. /package/dist/{standalone/.next → prod-next}/package.json +0 -0
  172. /package/dist/{standalone/.next → prod-next}/server/app/_global-error.meta +0 -0
  173. /package/dist/{standalone/.next → prod-next}/server/app/_not-found.meta +0 -0
  174. /package/dist/{standalone/.next → prod-next}/server/app/favicon.ico.body +0 -0
  175. /package/dist/{standalone/.next → prod-next}/server/app/favicon.ico.meta +0 -0
  176. /package/dist/{standalone/.next → prod-next}/server/chunks/318.js +0 -0
  177. /package/dist/{standalone/.next → prod-next}/server/middleware-manifest.json +0 -0
  178. /package/dist/{standalone/.next → prod-next}/server/next-font-manifest.js +0 -0
  179. /package/dist/{standalone/.next → prod-next}/server/next-font-manifest.json +0 -0
  180. /package/dist/{standalone/.next → prod-next}/server/pages-manifest.json +0 -0
  181. /package/dist/{standalone/.next → prod-next}/server/prefetch-hints.json +0 -0
  182. /package/dist/{standalone/.next → prod-next}/server/webpack-runtime.js +0 -0
  183. /package/dist/{standalone/.next → prod-next}/static/chunks/4bd1b696-deb4a0a1da1923b0.js +0 -0
  184. /package/dist/{standalone/.next → prod-next}/static/chunks/669-8103441c67b185da.js +0 -0
  185. /package/dist/{standalone/.next → prod-next}/static/chunks/701-df3ee5f1cf837b1a.js +0 -0
  186. /package/dist/{standalone/.next → prod-next}/static/chunks/794-25668765560cb197.js +0 -0
  187. /package/dist/{standalone/.next → prod-next}/static/chunks/app/_not-found/page-0b3785af737e7968.js +0 -0
  188. /package/dist/{standalone/.next → prod-next}/static/chunks/framework-b29f9083d3cda3b2.js +0 -0
  189. /package/dist/{standalone/.next → prod-next}/static/chunks/main-app-bfb36455d24b3e5a.js +0 -0
  190. /package/dist/{standalone/.next → prod-next}/static/chunks/main-bb33c46a9c25dee8.js +0 -0
  191. /package/dist/{standalone/.next → prod-next}/static/chunks/next/dist/client/components/builtin/global-error-dc53ab29e0491fe4.js +0 -0
  192. /package/dist/{standalone/.next → prod-next}/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  193. /package/dist/{standalone/.next → prod-next}/static/css/2e6ec4c80894e3c0.css +0 -0
  194. /package/dist/{standalone/.next → prod-next}/static/css/c593627ceef17a4b.css +0 -0
  195. /package/dist/{standalone/.next → prod-next}/static/media/36966cca54120369-s.p.woff2 +0 -0
  196. /package/dist/{standalone/.next → prod-next}/static/media/982ceffe7b733b3b-s.p.woff2 +0 -0
  197. /package/dist/{standalone/.next → prod-next}/static/media/b7387a63dd068245-s.woff2 +0 -0
  198. /package/dist/{standalone/.next → prod-next}/static/media/b8bfb68ab9ab617c-s.woff2 +0 -0
  199. /package/dist/{standalone/.next → prod-next}/static/media/e1aab0933260df4d-s.woff2 +0 -0
  200. /package/dist/{standalone/.next/static/jm3kxf8c6qGe0cYKCktaO → prod-next/static/sAWr5ATVuqk6Wqs18kAWs}/_ssgManifest.js +0 -0
  201. /package/dist/{standalone/public → public}/apple-touch-icon.png +0 -0
  202. /package/dist/{standalone/public → public}/favicon-96x96.png +0 -0
  203. /package/dist/{standalone/public → public}/favicon.ico +0 -0
  204. /package/dist/{standalone/public → public}/favicon.svg +0 -0
  205. /package/dist/{standalone/public → public}/file.svg +0 -0
  206. /package/dist/{standalone/public → public}/globe.svg +0 -0
  207. /package/dist/{standalone/public → public}/next.svg +0 -0
  208. /package/dist/{standalone/public → public}/og/og-default.png +0 -0
  209. /package/dist/{standalone/public → public}/site.webmanifest +0 -0
  210. /package/dist/{standalone/public → public}/tm_dark.png +0 -0
  211. /package/dist/{standalone/public → public}/tm_light.png +0 -0
  212. /package/dist/{standalone/public → public}/vercel.svg +0 -0
  213. /package/dist/{standalone/public → public}/web-app-manifest-192x192.png +0 -0
  214. /package/dist/{standalone/public → public}/web-app-manifest-512x512.png +0 -0
  215. /package/dist/{standalone/public → public}/window.svg +0 -0
@@ -0,0 +1,6 @@
1
+ /** Last path segment for UI — never show absolute machine paths. */
2
+ export function displayFileName(filePath: string): string {
3
+ const normalized = filePath.replace(/\\/g, "/")
4
+ const parts = normalized.split("/").filter(Boolean)
5
+ return parts[parts.length - 1] || filePath
6
+ }
@@ -7,8 +7,13 @@ import {
7
7
  discoverTaskmarkProjects,
8
8
  } from "@/lib/taskmark/discover"
9
9
  import type { DiscoveredProject } from "@/lib/taskmark/types"
10
+ import { isWorkspaceMode } from "@/lib/taskmark/workspace-mode"
10
11
 
11
- export type AutoconfigSource = "env_board" | "env_master" | "cwd"
12
+ export type AutoconfigSource =
13
+ | "env_board"
14
+ | "env_master"
15
+ | "cwd"
16
+ | "sibling"
12
17
 
13
18
  export type AutoconfigWorkspace = {
14
19
  source: AutoconfigSource
@@ -84,13 +89,54 @@ export function cwdCandidates(): string[] {
84
89
  return out
85
90
  }
86
91
 
92
+ /**
93
+ * Multi-git: product repo beside `<parentBasename>-taskmark` (or unique sibling).
94
+ */
95
+ export function resolveSiblingDedicatedBoard(fromDir: string): string | null {
96
+ const resolved = path.resolve(fromDir)
97
+ const parent = path.dirname(resolved)
98
+ const parentName = path.basename(parent)
99
+ const preferred = path.join(parent, `${parentName}-taskmark`)
100
+ const preferredBoard = resolveBoardAtPath(preferred)
101
+ if (preferredBoard) return preferredBoard
102
+
103
+ let entries: fs.Dirent[]
104
+ try {
105
+ entries = fs.readdirSync(parent, { withFileTypes: true })
106
+ } catch {
107
+ return null
108
+ }
109
+
110
+ const boards: string[] = []
111
+ for (const entry of entries) {
112
+ if (!entry.isDirectory() || !entry.name.endsWith("-taskmark")) continue
113
+ const board = resolveBoardAtPath(path.join(parent, entry.name))
114
+ if (board) boards.push(board)
115
+ }
116
+ if (boards.length === 0) return null
117
+ if (boards.length === 1) return boards[0]
118
+
119
+ const cwdBase = path.basename(resolved)
120
+ const parts = cwdBase.split("-").filter(Boolean)
121
+ for (let i = parts.length - 1; i >= 1; i--) {
122
+ const prefix = parts.slice(0, i).join("-")
123
+ const hit = boards.find((b) => path.basename(b) === `${prefix}-taskmark`)
124
+ if (hit) return hit
125
+ }
126
+
127
+ return null
128
+ }
129
+
87
130
  /**
88
131
  * Resolve a zero-config workspace without cookies.
89
132
  *
90
- * Precedence: TASKMARK_BOARD → TASKMARK_MASTER → cwd layouts.
91
- * Returns null when nothing valid is found (caller should use cookie setup).
133
+ * Precedence: TASKMARK_BOARD → TASKMARK_MASTER → cwd layouts → sibling *-taskmark.
134
+ * Returns null when nothing valid is found (caller should use cookie setup),
135
+ * or when workspace mode asked for the multi-project picker instead of a bind.
92
136
  */
93
137
  export function resolveAutoconfigWorkspace(): AutoconfigWorkspace | null {
138
+ if (isWorkspaceMode()) return null
139
+
94
140
  const boardEnv = readEnvPath("TASKMARK_BOARD")
95
141
  if (boardEnv) {
96
142
  const board = resolveBoardAtPath(boardEnv)
@@ -114,5 +160,10 @@ export function resolveAutoconfigWorkspace(): AutoconfigWorkspace | null {
114
160
  if (board) return workspaceFromBoard(board, "cwd")
115
161
  }
116
162
 
163
+ for (const candidate of cwdCandidates()) {
164
+ const sibling = resolveSiblingDedicatedBoard(candidate)
165
+ if (sibling) return workspaceFromBoard(sibling, "sibling")
166
+ }
167
+
117
168
  return null
118
169
  }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Touched by `taskmark dev` when board markdown changes so Next Fast Refresh
3
+ * re-runs server components that import this module.
4
+ */
5
+ export const DEV_RELOAD_TOKEN = "0"
@@ -129,7 +129,8 @@ export function discoverTaskmarkProjects(
129
129
  for (const entry of entries) {
130
130
  if (!entry.isDirectory()) continue
131
131
  if (shouldSkipDir(entry.name)) continue
132
- if (entry.name === "taskmark") continue
132
+ // A real `<dir>/taskmark` board already returned above, so a folder named
133
+ // "taskmark" here is an ordinary directory (e.g. a workspace root).
133
134
  visit(path.join(dir, entry.name), depth + 1)
134
135
  }
135
136
  }
@@ -1,11 +1,12 @@
1
1
  import type { DiscoveredProject } from "@/lib/taskmark/types"
2
2
 
3
- /** Label for dropdown; disambiguate when names collide. */
3
+ /** Label for dropdown; disambiguate when names collide (no filesystem paths). */
4
4
  export function projectOptionLabel(
5
5
  project: DiscoveredProject,
6
6
  all: DiscoveredProject[]
7
7
  ): string {
8
8
  const sameName = all.filter((p) => p.name === project.name)
9
9
  if (sameName.length <= 1) return project.name
10
- return `${project.name} ${project.projectPath}`
10
+ const index = sameName.findIndex((p) => p.id === project.id) + 1
11
+ return `${project.name} (${index})`
11
12
  }
@@ -30,13 +30,13 @@ export function validateMasterFolder(
30
30
  return {
31
31
  ok: false,
32
32
  code: "not_found",
33
- error: `Folder not found: ${masterPath}`,
33
+ error: "Folder not found. Check the path and try again.",
34
34
  }
35
35
  }
36
36
  return {
37
37
  ok: false,
38
38
  code: "unreadable",
39
- error: `Cannot read folder: ${masterPath}`,
39
+ error: "Cannot read that folder. Check permissions and try again.",
40
40
  }
41
41
  }
42
42
 
@@ -44,7 +44,7 @@ export function validateMasterFolder(
44
44
  return {
45
45
  ok: false,
46
46
  code: "not_directory",
47
- error: `Path is not a folder: ${masterPath}`,
47
+ error: "That path is not a folder.",
48
48
  }
49
49
  }
50
50
 
@@ -55,7 +55,7 @@ export function validateMasterFolder(
55
55
  return {
56
56
  ok: false,
57
57
  code: "unreadable",
58
- error: `Cannot scan folder: ${masterPath}`,
58
+ error: "Cannot scan that folder. Check permissions and try again.",
59
59
  }
60
60
  }
61
61
 
@@ -0,0 +1,24 @@
1
+ import path from "node:path"
2
+
3
+ /**
4
+ * Workspace (multi-project) mode — `taskmark` / `taskmark open` / `--workspace`.
5
+ *
6
+ * Board-bound commands (`serve`, `dev`) auto-config a single board from env or
7
+ * cwd. Workspace mode turns that off so the cookie-based master folders and the
8
+ * app bar project picker drive which board is shown.
9
+ */
10
+ export function isWorkspaceMode(): boolean {
11
+ const raw = process.env.TASKMARK_WORKSPACE?.trim().toLowerCase()
12
+ return raw === "1" || raw === "true"
13
+ }
14
+
15
+ /** Directory `taskmark` was invoked from; seeds the setup wizard input. */
16
+ export function workspaceStartPath(): string {
17
+ for (const raw of [
18
+ process.env.TASKMARK_WORKSPACE_ROOT,
19
+ process.env.INIT_CWD,
20
+ ]) {
21
+ if (raw && raw.trim()) return path.resolve(raw.trim())
22
+ }
23
+ return ""
24
+ }
@@ -1,4 +1,7 @@
1
- import { resolveAutoconfigWorkspace } from "@/lib/taskmark/autoconfig"
1
+ import {
2
+ resolveAutoconfigWorkspace,
3
+ type AutoconfigSource,
4
+ } from "@/lib/taskmark/autoconfig"
2
5
  import { discoverTaskmarkProjectsFromMasters } from "@/lib/taskmark/discover"
3
6
  import { validateMasterFolder } from "@/lib/taskmark/validate"
4
7
  import type { DiscoveredProject } from "@/lib/taskmark/types"
@@ -7,7 +10,7 @@ export type ConfiguredWorkspace = {
7
10
  masters: string[]
8
11
  projects: DiscoveredProject[]
9
12
  /** How the workspace was resolved; null means cookie/manual masters. */
10
- source: "env_board" | "env_master" | "cwd" | "cookies" | null
13
+ source: AutoconfigSource | "cookies" | null
11
14
  /** When true, UI is locked to the auto-bound board(s) (skip setup). */
12
15
  autoconfig: boolean
13
16
  }
package/next.config.ts CHANGED
@@ -10,17 +10,12 @@ const nextConfig: NextConfig = {
10
10
  // When installed under a board with its own lockfile, Next would otherwise
11
11
  // treat the board as the workspace root and break `@/` resolution.
12
12
  outputFileTracingRoot: packageDir,
13
- // `taskmark serve` uses standalone; `taskmark build` (static hosting) uses export.
14
- output: staticExport ? "export" : "standalone",
13
+ // Static hosting uses `export`; local `taskmark serve` uses `next start`
14
+ // against a slim prebuilt `.next` (see scripts/prepare-standalone.mjs).
15
+ output: staticExport ? "export" : undefined,
15
16
  images: staticExport ? { unoptimized: true } : undefined,
16
17
  // Static build stubs server actions; skip tsc against those temporary stubs.
17
18
  typescript: staticExport ? { ignoreBuildErrors: true } : undefined,
18
- // Avoid tracing prior dist/standalone into itself (nested copies).
19
- outputFileTracingExcludes: staticExport
20
- ? undefined
21
- : {
22
- "*": ["./dist/**/*", "./out/**/*"],
23
- },
24
19
  webpack: (config) => {
25
20
  config.resolve.alias = {
26
21
  ...config.resolve.alias,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@taskmark/ui",
3
- "version": "0.2.4",
4
- "description": "Local Taskmark board UI — install in a board folder and run `npx taskmark serve` or `npx taskmark build`",
3
+ "version": "0.2.6",
4
+ "description": "Taskmark board UI — run globally for setup/project picker, or install in a board folder to open that board with `npx taskmark`",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "bin": {
@@ -15,7 +15,8 @@
15
15
  "lib",
16
16
  "public",
17
17
  "scripts",
18
- "dist/standalone",
18
+ "dist/prod-next",
19
+ "dist/public",
19
20
  "next.config.ts",
20
21
  "postcss.config.mjs",
21
22
  "tsconfig.json",
@@ -31,7 +32,9 @@
31
32
  "node": ">=18"
32
33
  },
33
34
  "scripts": {
34
- "dev": "next dev",
35
+ "dev": "node ./bin/taskmark.js dev",
36
+ "dev:workspace": "node ./bin/taskmark.js dev --workspace",
37
+ "open": "node ./bin/taskmark.js open",
35
38
  "build": "next build --webpack && node scripts/prepare-standalone.mjs",
36
39
  "build:static": "node scripts/build-static.mjs",
37
40
  "start": "next start",