Skip to content

Conversation

@p2edwards
Copy link
Contributor

@p2edwards p2edwards commented Nov 20, 2025

Add a helper script for running the backend and frontend independently on 2 different branches.

💭 Notes

With two distinct copies of kobotoolbox/kpi checked out, this script will make it so that the app served by kpi-backend will point to the frontend dev server running from kpi-frontend:

  ./scripts/split-frontend.sh \
    -f ~/kobo/kpi-frontend \
    -b ~/kobo/kpi-backend

Then, you can switch kpi-frontend and kpi-backend branches independently from one another.

Use case

Day-to-day branch switching

  1. You can checking out a series of frontend pull requests that offer frontend-only app changes, but that differ on backend due to being on different base branches. You can keep your backend on main during this while you test the JS changes.
  2. Likewise, if you have backend changes in your worktree, you can check out any frontend branch to a new one without stashing, merging, cherry-picking, anything.

Parallel previews

  1. Testing multiple frontend combinations: live preview your frontend across multiple differently-configured local backend instances to preview combinations of constance variables / stripe / mfa. (This would be useful when dealing with things like Terms of Service update, MFA login, or custom project fields.)

Assumptions for this PR

  • You're running npm run watch on the host (outside of the kpi container that has your backend running)
  • You're able to run kpi container normally, the production build is working and it has its static files collected, etc.

(these restrictions may be relaxed when the backend and frontend are decoupled further)

Implementation notes

The script is a wrapper for essentially a 1-liner:

  watchexec --watch ~/kobo/kpi-fe/webpack-stats.json \
    -- cp ~/kobo/kpi-fe/webpack-stats.json \
          ~/kobo/kpi-be/webpack-stats.json

To avoid the need to install watchexec or similar binary separately, split-frontend.sh borrows a CLI watcher from uv (PyPI) or npx (npm).

  • If uv is installed (backend developers), it will use uvx and the [email protected] package.
  • If npm is installed (frontend developers), it will use npx and the [email protected] package.

👀 Preview steps

  1. ℹ️ backend: bring up your kobo-install dev instance as you would normally
    • e.g. 📁~/kobo/kpi, 💻 ../kobo-install/run.py (…), 🌐 kf.kobo.local
  2. ℹ️ frontend: create another kpi clone and start the frontend server on host
    • e.g. 📁~/kobo/kpi-fe, 💻 npm run watch, 🌐 localhost:3000
  3. in either folder, check out this PR branch (dev-1304-disjoint-frontend) and run the new script
    • e.g. 💻 ./scripts/split-frontend.sh -b ~/kobo/kpi -f ~/kobo/kpi-fe
  4. 🟢 verify that the git branches of 📁~/kobo/kpi and 📁~/kobo/kpi-fe can be switched independently, and the app continues.
    • example:
      • in 📁~/kobo/kpi-fe, check out a PR that only changes the frontend anji/dev-1169-select-one-to-mantine
      • in 📁~/kobo/kpi-be, check out a PR that only changes the backend dev-1278-data-endpoint-pagination
      • 🟢 see that 🌐 kf.kobo.local shows a preview with changes from both branches, even though there is not git branch or working tree that contains both.
diagram
---
config:
  look: neo
  layout: dagre
---
flowchart TB
    n2["backend"] -- "<span style=background-color:>dev-1304-disjoint-frontend</span>" --> n5@{ label: "ℹ️ bring up your kobo-install dev instance normally<br><br>e.g. 📁<b style=\"color:\">~/kobo/kpi</b>(backend)<br><b style=\"color:\"></b>🌐<b style=\"color:\">kf.kobo.local</b><br>" }
    n3["frontend"] --> n1["ℹ️ clone another copy of kpi for the frontend<br><br>e.g. 📁<b>~/kobo/kpi-fe</b><br>"]
    n1 -- "<span style=background-color:>dev-1304-disjoint-frontend</span>" --> n4@{ label: "start a frontend dev server on host<br><br><b>npm install</b><br><b>npm run watch<br><br></b><span style=\"background-color:\">🌐</span><b>localhost:3000</b>" }
    n4 --> n6["<br>Run the script: <br><br> ~/kobo/kpi/scripts/split-frontend.sh  \ <br>-b ~/kobo/kpi \ <br> -f ~/kobo/kpi-fe<br><br><br>"]
    n5 -- <br> --> n6
    n6 --> n8["Switch branch in <br><b>📁~/kobo/kpi<br></b>(backend)"] & n9["Switch frontend branch in <br><b>📁~/kobo/kpi-fe</b><br>(frontend)<br>"]
    n8 -- "e.g. <a title=kobotoolbox/kpi:dev-1278-data-endpoint-pagination href=https://github.com/kobotoolbox/kpi/tree/dev-1278-data-endpoint-pagination><span class=css-truncate-target>dev-1278-data-endpoint-pagination</span></a>" --> n7["🟢 See that the frontend and backend updates apply independently"]
    n9 -- "e.g. <a title=kobotoolbox/kpi:anji/dev-1169-select-one-to-mantine href=https://github.com/kobotoolbox/kpi/tree/anji/dev-1169-select-one-to-mantine><span class=css-truncate-target>anji/dev-1169-select-one-to-mantine</span></a>" --> n7

    n2@{ shape: terminal}
    n5@{ shape: tag-proc}
    n3@{ shape: terminal}
    n1@{ shape: tag-proc}
    n4@{ shape: tag-proc}
    n6@{ shape: tag-proc}
    n8@{ shape: terminal}
    n9@{ shape: terminal}
    n7@{ shape: terminal}
     n2:::be
     n5:::be
     n3:::fe
     n1:::fe
     n4:::fe
     n6:::merge
     n8:::be
     n9:::fe
     n7:::merge
    classDef be fill:#BBDEFB
    classDef merge fill:#C8E6C9
    classDef fe fill:#FFF9C4
    style n6 fill:#C8E6C9
Loading

Add helper script for running backend and frontend on 2 different branches
@p2edwards p2edwards self-assigned this Nov 21, 2025
@p2edwards p2edwards added the workflow Related to development process label Nov 21, 2025
@p2edwards p2edwards marked this pull request as ready for review November 24, 2025 14:47
@p2edwards p2edwards requested review from duvld and removed request for jnm, noliveleger and olive-KTB November 24, 2025 14:47
Copy link
Member

@duvld duvld left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe an issue with PR testing steps, my workflow uses npm watch in the docker container, so it may produce different results than what the PR is expecting the workflow to be

Script fails initially due to insufficent permissions for copying webpack stats on a fresh install. Node modules, staticfiles and webpack stats json have root ownership

After changing ownership on my machine this is the output of the script:

./scripts/split-frontend.sh -b . -f ../kpi-fe
  backend:  /home/mako/Dev/Kobo/kobo-main-2/kpi
  frontend: /home/mako/Dev/Kobo/kobo-main-2/kpi-fe
++ npx
++ command -v bunx
++ command -v npx
++ echo npx
+ npx [email protected] chokidar webpack-stats.json '--command=cp /home/mako/Dev/Kobo/kobo-main-2/kpi-fe/webpack-stats.json /home/mako/Dev/Kobo/kobo-main-2/kpi/webpack-stats.json'
+ command -v bunx
+ command -v npx
+ echo npx
npx
+ exit 0

which is not the expected output

@p2edwards p2edwards requested a review from duvld November 24, 2025 20:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

workflow Related to development process

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants