frappe / frappe/studio

Studio editor cannot load custom components when an app is installed from outside apps/ (via .pth, e.g. a git worktree)

Open
#240 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.