Desktop Application & Vue Frontend Updates: GSoC 2025 Final Report

gsoc-cover

Hey Everyone ๐Ÿ˜Š,

Welcome to my final blog for Google Summer of Code 2025 for the project Desktop Application & Vue Frontend Updates. At the begining of each heading you can see Deliverable, which gives information for users to know about the feature with no dev-terms(or very less at best ๐Ÿ˜‰). For the dev side, read on!

What is the Project about ๐Ÿ–ฅโœจ


Desktop Application & Vue Frontend Updates: The project works on the Vue Simulator and aims at completing the vue-simulator. We have achieved several milestones like Authentication model, a beautiful Release Pipeline for Tauri simulator, version sync for v0 and v1, a brand new Testbench UI and best of all pushed vue-simulator to production. Letโ€™s dive into them right away !!

Major statures that have been added and merged include:

  • ๐Ÿš€ Pushing the Vue-Simulator to production
  • ๐Ÿ” Authentication model for Tauri Simulator
  • ๐Ÿ“ Conventional-commits workflow
  • โšก Release Pipeline for Tauri Simulator
  • ๐ŸŽจ An improved Testbench UI/UX
  • ๐Ÿ”„ Legacy feature sync to v0 and v1

Project Board


1. Pushing Vue-Simulator to Production


Deliverable: We have finally pushed the vue-simulator to production ๐ŸŽ‰. We faced a lot of tricky problems along the way but finally after 4 GSoC projects we are here with vue-simulator in Production. The users can use legacy simulator by just clicking on the simulator at the homepage (URL - https://circuitverse.org/simulator). For using vue simulator they need to change the URL to https://circuitverse.org/simulatorvur which is equivalent to https://circuitverse.org/simulatorvue?simver=v0. This sets the v0 (base) version for vue-simulator. Users can also change the URL to https://circuitverse.org/simulatorvue?simver=v1, this sets the version to v1. We will be using v1 to rollout the beta updates for new features ๐Ÿงช, after thorough testing and positive user response ๐Ÿ‘ weโ€™ll move those updates to v0. Users can freely choose to work on either of the three versions: legacy, v0, v1. The working of the Embed view can be seen in the video attached below. ๐ŸŽฅ


Letโ€™s tape the tale ๐Ÿ“–: Pushing the vue-simulator to production has been the biggest objective for this project. The vision of vue-simulator being giving users option to use the various versions at will gave rise to a lot of contingencies โšก. Letโ€™s start with the first major bug ๐Ÿ› we faced:

1A. The Embed-Vue failure โŒ #643

When a user saves a circuit it can be viewed in the Dashboard ๐Ÿ“‚. When going into the Embed view i.e. when we click on more under a circuit we are directed to another page where we see the Embed view. The issue was that the paths were only handled properly for the legacy simulator causing the whole vue-simulator being loaded in the Embed area instead of just a lighter version of the simulator like how it is meant to be for the embedded format. To fix this we had to really delve into the codebase ๐Ÿ› ๏ธ. Here on is the crux of the situation and how we tackled it.

Problem โŒ

  • The simulatorVersion was not stored as a separate column in the database ๐Ÿ—„๏ธ.
  • Many older projects did not have simulatorVersion defined at all, since they were created using the legacy simulator ๐Ÿ•ฐ๏ธ.
  • Because of this, we could not reliably read the field directly without risking errors โš ๏ธ or breaking compatibility.

Solution โœ…

Step 1: Extract the simulator version from project data ๐Ÿ“Š
We added logic in the Project model to safely read simulatorVersion from the JSON field.

  • If the field exists, we use its value.
  • If it does not exist (as in legacy projects), we default to "legacy".

This gave us a consistent way to determine whether a project was created with the new Vue simulator or the old legacy one.

Step 2: Add a helper method to detect Vue simulator projects ๐Ÿ”
In the model, we introduced a method that checks the simulator version and returns whether the project is a Vue simulator project or not.

  • Vue simulators are identified by versions v0 and v1.
  • Legacy simulators fall back to the default "legacy" tag.

Step 3: Decide the embed path in the controller โš™๏ธ In the Project controller, we used the helper method to set the correct embed path.

  • If the project uses Vue simulator, we assign the Vue embed path.
  • Otherwise, we assign the legacy embed path.

This kept the decision-making clean and consistent.

Step 4: Render the correct simulator in the view ๐Ÿ–ผ๏ธ In the show page, instead of hardcoding the iframe path, we used the path determined by the controller.
This ensures that the correct simulator (legacy or Vue) is embedded based on the projectโ€™s version.

Why this approach works ๐Ÿ’ก

  • โœ… It supports both old and new projects without breaking anything.
  • โœ… It avoids errors when simulatorVersion is missing.
  • โœ… It centralizes the version-handling logic inside the model, keeping the controller and view simple.
  • โœ… It makes the application future-proof ๐Ÿ”ฎ.

Here is the working of Embed ๐ŸŽฅ

1B. The Docker Failure ๐ŸณโŒ

For Pushing the vue-simulator we needed to change the old hash pointing to the vue-submodule in the primary codebase to the new hash pointing to the current vue-submodule. This step in theory was supposed to be just 2 steps:

  • Step 1: cd into the cv-frontend-vue submodule from the master and use git branch to switch to main
  • Step 2: Raise the PR for it.

But the technicalities of the process overshadowed us and we ran straight into a wall. The Docker publish image workflow was failing! ๐Ÿšจ It had to pass, else we couldnโ€™t merge the PR (PR #6012). Now we had to review and fix it as soon as possible. This turned out to be trickier than we thought. It earlier seemed like just an issue due to missing v0 in the outdir. We tried fixing it that way but failed. Finally, after a lot more debugging, this is how we solved it.

Problem Statement: Docker build failed with โ€œnot foundโ€ error when copying Vue simulator files from /public/simulatorvue/.
Root Cause: Vite config used relative path ../public/simulatorvue/ with undefined DESKTOP_MODE, causing unpredictable build output location.
Solution: (PR #6061)

  • Created explicit output directory /output/simulatorvue/
  • Set DESKTOP_MODE=false for consistent Vite behavior
  • Added fallback copy logic to handle different output paths
# In simulator_vue_build stage:
RUN mkdir -p /output/simulatorvue
ENV DESKTOP_MODE=false
RUN npm run build
RUN cp -r public/simulatorvue/* /output/simulatorvue/ || cp -r ../public/simulatorvue/* /output/simulatorvue/

# In final stage:
COPY --from=simulator_vue_build /output/simulatorvue/ /usr/src/app/public/simulatorvue

2. Authentication Model for Web and Tauri Simulator ๐Ÿšช๐Ÿ”’


Deliverable: Added an Authentication model to Tauri Simulator. For the Tauri simulator the users now will face an Authentication model specifically made for the application. They only have to login once, their profiles will be stored up until they themselves log out from the application. โœ…


Technical Tale: The reason we needed a separate Authentication model for vue simulator is because of Tauri. Earlier we were simply changing the path in the URL to direct to the Login page of Circuitverse for Authentication. This particular method fails for the Tauri simulator because:

  • It is a standalone simulator with no connection to the primary codebase. ๐Ÿ–ฅ๏ธ
  • We want the Tauri simulator to also work when user is offline. ๐ŸŒโŒ
  • We cannot redirect links like we do in web in Tauri. ๐Ÿ”—๐Ÿšซ

To answer those needs, it was the need of the hour to create an authentication model for the vue-simulator and so did we deliver. The authentication system in the CircuitVerse frontend is built using Vue 3 with TypeScript.
It handles both login and signup flows via API requests to the CircuitVerse backend. ๐Ÿ”„

  • Frontend Tech: Vue 3 + TypeScript + Pinia (Auth Store) ๐Ÿ› ๏ธ
  • API Layer: Fetch (with Tauri HTTP plugin) ๐ŸŒ
  • Backend Endpoints:
    • POST /api/v1/auth/login ๐Ÿ”‘
    • POST /api/v1/auth/signup ๐Ÿ“

2A. Authentication Flow ๐Ÿ”„

  1. Auth Modal Handling ๐ŸชŸ

    • A modal component (authModal) is used to toggle between login and signup. ๐Ÿ”„
    • Users can switch modes dynamically without leaving the page. ๐Ÿ”
  2. Form Validation โœ…

    • Basic client-side validation rules:
      • Required fields must not be empty. ๐Ÿšซ
      • Valid email format (/.+@.+\..+/). ๐Ÿ“ง
      • Password must be at least 6 characters. ๐Ÿ”’
  3. Request Building ๐Ÿ› ๏ธ

    • Depending on mode (isLoginMode), the request body changes:
      • Login: { email, password } ๐Ÿ”‘
      • Signup: { name, email, password } ๐Ÿ“
    • Requests are sent as JSON with appropriate headers. ๐Ÿ“ค
  4. API Communication ๐ŸŒ

    • Uses the fetch function (via Tauri plugin when inside desktop app).
    • On success, the backend responds with an auth token. ๐Ÿท๏ธ
  5. State Management ๐Ÿ—‚๏ธ

    • The received token is stored in the Auth Store (useAuthStore()).
    • Store handles:
      • Saving token ๐Ÿ’พ
      • Fetching user ID ๐Ÿ†”
      • Sign-out / token removal ๐Ÿšช
  6. Error Handling โš ๏ธ

    • Common error responses:
      • 401 Unauthorized โ†’ Invalid credentials โŒ
      • 404 Not Found โ†’ User does not exist ๐Ÿ”
      • 409 Conflict โ†’ User already exists โš”๏ธ
      • 422 Unprocessable Entity โ†’ Invalid input ๐Ÿ›‘
    • Errors are shown to the user via a snackbar notification system. ๐Ÿ””

These are some of the snaps of the Authentication model and its working video-

Authentication sample image 1 Authentication sample image 2 Authentication sample image 3

3. Conventional-Commit ๐Ÿš€


Deliverable: Now the commits to the cv-frontend-vue require to follow conventional-commits ๐Ÿ“. This is to add more meaning to commits for both humans and machines ๐Ÿค–.


Why and How we did it: We have added conventional-commit to the workflows, ensuring smoothness in the Automation for version tag generation ๐Ÿ”„. This also helps give the maintainers a good holistic view of where the simulator stands at, in turn helping them choose the minor, patch, or major version bump in the Release ๐ŸŽฏ. (PR #656) From here on, the commits made by everyone would need to follow the conventional-commits โœ…. Some of them are as follows:

Types ๐Ÿ› ๏ธ

The type indicates the nature of the change:

  • feat: โœจ A new feature
  • fix: ๐Ÿ› A bug fix
  • docs: ๐Ÿ“š Documentation changes
  • style: ๐ŸŽจ Code style/formatting changes (no logic change)
  • refactor: ๐Ÿ”„ Code changes that neither fix a bug nor add a feature
  • perf: โšก Performance improvements
  • test: ๐Ÿงช Adding or updating tests
  • chore: ๐Ÿ› ๏ธ Build process, tooling, or maintenance tasks
  • ci: ๐Ÿค– CI/CD related changes

4. Automating Cross-Platform Desktop Releases ๐Ÿš€๐Ÿ’ป


Deliverable: An Automated Release pipeline has been added to the vue-simulator. With one click by the maintainers a Release is created and assets (Artefacts for Windows, Mac and Linux subsystems) are attached with the Latest Release under Releases heading on cv-frontend-vue primary codebase. There is also another file called CHANGELOG that is created, it holds the logs of current and all of the previous Releases. ๐Ÿ“œ


How we did it? - One of the key deliverables for the GSoC project was a reliable release pipeline for the CircuitVerse desktop app. We initially explored fully automated tools like semantic-release and release-it!, but they offered less manual control than we needed. The ideal solution needed to balance powerful automation with maintainer oversight. โš–๏ธ

The breakthrough was using GitHub Actionsโ€™ workflow_dispatch. This allows us to trigger the release manually, providing input on the version type (major, minor, or patch), giving us the perfect blend of automation and control. This approach culminated in the final workflow that now powers our desktop releases. ๐ŸŽฏ

4A. The Release Workflow Code ๐Ÿ› ๏ธ

The entire process is encapsulated in a single GitHub Actions workflow file. Itโ€™s composed of two primary jobs: build-tauri to compile the application across all platforms, and create-release to package and publish the final release. ๐Ÿ“ฆ

4B. How It Works ๐Ÿง

The workflow operates in two sequential jobs:
Job 1: build-tauri
This job is the workhorse, responsible for compiling the application. It uses a matrix strategy to run three parallel jobs, one for each target OS: ubuntu-latest, windows-latest, and macos-latest. This is the key to efficient cross-platform building. ๐ŸŒ

  • Environment Setup: Each job begins by checking out the code and setting up the required toolchains, like Node.js and Rust. Crucially, it also installs OS-specific dependencies needed for compilation, such as libwebkit2gtk-4.1-dev on Ubuntu or wixtoolset on Windows. ๐Ÿ› ๏ธ

  • Dependency Caching: To dramatically speed up build times on subsequent runs, the workflow caches both the Node.js (.npm) and Rust (.cargo, target) dependency directories. This avoids re-downloading and re-compiling hundreds of packages every time. โšก

  • Build & Upload: The job then runs the tauri build command, which creates the native application installers. Once complete, it uses the actions/upload-artifact action to save these installers, making them available to the next job in the workflow. ๐Ÿ“ค

Job 2: create-release
This job only runs after all three build jobs have completed successfully (needs: build-tauri). It handles the final packaging and publishing. ๐Ÿ“ฆ

  • Artifact & Code Aggregation: It begins by downloading all the build artifacts (the installers for Linux, macOS, and Windows) from the previous job. It also checks out the repository with fetch-depth: 0 to ensure it has the full git history, which is essential for the next step. ๐Ÿ“‚

  • Automated Changelog: The conventional-changelog-action scans the git history since the last release tag. Based on conventional commit messages (like feat:, fix:, etc.), it automatically generates professional, well-formatted release notes. ๐Ÿ“

  • Versioning: A bash script then determines the new version number. It fetches the latest git tag (e.g., v1.2.3), parses it, and increments the version based on the version-bump input (patch, minor, or major) that was provided when the workflow was triggered. ๐Ÿ”ข

  • Publishing: Finally, using the GitHub CLI, the script creates a new GitHub Release. It tags the commit with the new version, sets the release title, attaches the auto-generated changelog as the release notes, and uploads all the cross-platform installers as release assets. ๐Ÿš€

The Final Product (PR #636)โœจ
The result is a beautifully simple and powerful release process. Now, any maintainer can go to the repositoryโ€™s โ€œActionsโ€ tab, select the โ€œManually Triggered Desktop Releaseโ€ workflow, choose whether itโ€™s a major, minor, or patch release, and click โ€œRun workflow.โ€ ๐Ÿ–ฑ๏ธ

Release Pipelines sample image 2

From there, everything is automated. Within minutes, a new, cross-platform release is published to GitHub, complete with installers for every OS and a professional changelog, ready for our users. This pipeline removes manual effort, eliminates human error, and ensures our releases are consistent and reliable every single time. โœ…

Release Pipelines sample image 2

5. The Artistic new Testbench UI ๐ŸŽจโœจ

This has been the artistic side of the project. We have had the Testbench UI for a while now, up to now it had received 2 major UI revamps during some of the previous GSOC projects. This time we went outside the current colour palette a bit. We have used the classic Circuitverse green with white, which gives it a soft and user-friendly look. ๐Ÿ’š๐Ÿค

Here are some snapshots of the new Testbench UI ๐Ÿ“ธ

Testbench sample image 1 Testbench sample image 2

Here is a video showcasing the working of the new Testbench

6. Legacy version sync to versions v0 and v1 ๐Ÿ”„๐Ÿ“‚


Deliverable: This was a requirement for Versioning of vue-simulator. This is not a new feature but rather a major pillar of versioning. ๐Ÿ—๏ธ


And what is that major Pillar? After the previous yearโ€™s GSOC project on implementing version control, we needed to sync the legacy simulator versions to the versioned folders while syncing the changes in the src folder to v0 and v1 too. This was carried out in 3 steps. ๐Ÿ› ๏ธ Step 1: This step was brute-force copying all of the files from the src folder to the versioned directories v0 and v1. ๐Ÿ“‹
Step 2: Then we compared all of the changes that existed in src and not in v0 and v1. We came across many small features that were missing for src which needed to be re-written, for eg: the version mismatch dialogue for the vue simulator in openOffline.vue. (PR #599) ๐Ÿ› ๏ธ
Step 3: This was the part where we tested the result of the change. Since the change built up a massive PR, this step took time and also proved beneficial. We came across a few shortcomings, the major one being the preview circuits for version v1 going into infinite reload. This was created due to an error that occurred during the feature sync to the v1 folder. (PR #647) ๐Ÿ›๐Ÿ”„



Learning ๐Ÿ“šโœจ

I learned a lot related to working of things in software. Most of all I learned how to look for solutions. I really liked the part where I sat plannig with my mentors as to how we are going to be approaching different contingencies. We implemented many ideas and had to leave behind many too. I learned a lot about GitHub Actions, Vue.js, Rust, and TypeScript a lot. Also got to try my hands on Rails and Ruby too. ๐Ÿ› ๏ธ

These few weeks taught me a lot about how the industry works and how work is done. I learned a lot of things outside coding and got to meet many crazy people and learn from them. ๐ŸŒŸ

Conclusion ๐ŸŽข๐ŸŽฏ

My journey so far has been nothing but a roller-coaster. Each week I stumbled upon things I didnโ€™t know, then learned it, bugged my mentor about it, experimented with it and then implemented it. It has truly been a developerโ€™s dream till now. My mentors and CircuitVerse community have been very helpful and inspirational in my little journey. Looking forward to contribute and learn more. ๐Ÿš€

I would especially like to thank my mentors Aryann Dwivedi and Niladri Adhikary for being amazing mentors and guiding my way out of the walls I kept head-butting into, I would also like to thank Arnab Das, Aboobacker MK, Vedant Jain and other mentors and circuitverse contributors for helping and mentoring me throught the journey. ๐Ÿ™๐ŸŒŸ