Studio editor cannot load custom components when an app is installed from outside apps/ (via .pth, e.g. a git worktree)
- Dominant language
- Vue
- Stars
- 280
- Forks
- 98
- Avg merge
- 1d 30m
- Merged PRs (30d)
- 11
Description
### Summary
When a frappe app is installed from a checkout **outside `apps/`**, the Studio editor renders its pages with **every custom Vue component missing**. The canvas looks empty and nothing on screen explains why — the only signal is a console error per component.
### Why it happens
Studio answers "where does app X live?" in two places, and they use different mechanisms.
**The backend follows Python's view.** `studio.api.get_custom_vue_components` resolves component paths through `frappe.get_app_source_path(frappe_app)`, which resolves the installed package — i.e. wherever `env/lib/python*/site-packages/.pth` points.
**The dev server follows the filesystem's view.** `frontend/vite.config.js` builds `server.fs.allow` from `apps/`, plus entries *in* `apps/` whose realpath escapes it:
```js
const appSymlinkedSources = fs.readdirSync(appsDir).flatMap((entry) => {
const realPath = fs.realpathSync(path.join(appsDir, entry))
if (realPath.startsWith(appsDir + path.sep)) return [] // inside apps/, nothing to add
const studioDir = path.join(realPath, "studio") // symlink → allow its studio/
return fs.existsSync(studioDir) ? [studioDir] : []
})
```
That covers an app **symlinked into** `apps/`. It does not cover an app **installed from** somewhere else, where `apps/` is a real directory (a different branch checked out, say) while the `.pth` points elsewhere:
| layout | `apps/` | `.pth` | in `fs.allow`? |
|---|---|---|---|
| normal | real dir | `apps/` | ✅ |
| worktree, symlinked in | symlink → worktree | worktree | ✅ via `appSymlinkedSources` |
| **worktree, installed via `.pth`** | real dir (other branch) | worktree | ❌ **not covered** |
In the third row the two halves disagree: the API hands the editor paths under the worktree, and the dev server — which never heard of it — answers **403**. Studio is refusing to serve paths Studio just advertised.
This arrived with the (correct) tightening in `a4b6c57 fix(vite): restrict serving from apps dir + app symlinked dirs`, which replaced `936b229 fix(vite): allow serving files from bench root to support worktrees`. Bench-root was far too wide; the replacement just assumed a symlink is the only way an app lives outside `apps/`.
### Symptom
One error per custom component, and nothing rendered for any of them:
```
Error fetching custom component template KbArticleContent: TypeError: Failed to fetch
dynamically imported module: http://site:8080/Users/.../.worktrees/kb-portal/studio/helpdesk/components/KbArticleContent.vue?raw
```
It is `fs.allow` and not a malformed URL — fetching that path directly returns `403`, and so does the `/@fs/`-prefixed form:
```
GET /Users/.../components/KbCopyLink.vue?raw → 403
GET /@fs/Users/.../components/KbCopyLink.vue?raw → 403
```
(Careful when checking a page-script path instead: an extensionless request returns `200` because it hits Vite's SPA fallback and gets `index.html`, not the file. Only the `?raw` component fetch gives a straight answer.)
### Steps to reproduce
1. Check out an app with a `studio/` folder into a git worktree outside `apps/` and install it, so `.pth` points at the worktree while `apps/` stays a real directory.
2. Give one of its studio pages a custom Vue component.
3. Open that page in the Studio editor with the dev server running.
**Expected:** the page renders with its custom components.
**Actual:** they are all missing; console shows one "Failed to fetch dynamically imported module" each.
Reproduced on `develop` at `58de51d`.
### Workaround
Symlink the app into `apps/` instead of installing it from the worktree — that hits the row `appSymlinkedSources` already handles. Not always possible: it costs you whatever checkout `apps/` currently holds.
### Fix
Read the same registry the backend resolves through — the `.pth` files — and allow each app's `studio/` folder, keeping the scope as narrow as `a4b6c57` intended. PR: #241
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with frontend/vite.config.js and the studio.api.get_custom_vue_components entry point, then reproduce the worktree layout described in the issue. Verify the custom component’s ?raw request and Studio page behavior; done means the advertised component paths are served without 403 errors and the components render.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, python, vite
- Domain
- frontend, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100