{"id":13728306,"url":"https://github.com/marcomq/nimview","last_synced_at":"2025-04-09T20:10:15.959Z","repository":{"id":42439714,"uuid":"303786129","full_name":"marcomq/nimview","owner":"marcomq","description":"A Nim/Webview based helper to create Desktop/Server applications with Nim/C/C++ and HTML/CSS","archived":false,"fork":false,"pushed_at":"2022-09-18T10:25:23.000Z","size":4102,"stargazers_count":152,"open_issues_count":8,"forks_count":11,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-02T13:02:14.961Z","etag":null,"topics":["c-library","cpp-library","desktop","html","http-server","nim","nim-lang","python","user-interface","webview"],"latest_commit_sha":null,"homepage":"","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcomq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-13T17:51:30.000Z","updated_at":"2025-02-27T12:44:19.000Z","dependencies_parsed_at":"2022-08-12T10:00:40.128Z","dependency_job_id":null,"html_url":"https://github.com/marcomq/nimview","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomq%2Fnimview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomq%2Fnimview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomq%2Fnimview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomq%2Fnimview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcomq","download_url":"https://codeload.github.com/marcomq/nimview/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103871,"owners_count":21048245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-library","cpp-library","desktop","html","http-server","nim","nim-lang","python","user-interface","webview"],"created_at":"2024-08-03T02:00:40.238Z","updated_at":"2025-04-09T20:10:15.925Z","avatar_url":"https://github.com/marcomq.png","language":"Nim","readme":"# Nimview \n![License](https://img.shields.io/github/license/marcomq/nimview) \n[![Build Status](https://github.com/marcomq/nimview/actions/workflows/linux.yml/badge.svg?branch=main)](https://github.com/marcomq/nimview/actions/workflows/linux.yml)\n[![Build Status](https://github.com/marcomq/nimview/actions/workflows/windows.yml/badge.svg?branch=main)](https://github.com/marcomq/nimview/actions/workflows/windows.yml)\n[![Build Status](https://github.com/marcomq/nimview/actions/workflows/macos.yml/badge.svg?branch=main)](https://github.com/marcomq/nimview/actions/workflows/macos.yml)\n\n\nA lightweight cross platform UI library for Nim, C, C++ or Python. The main purpose is to simplify creation of online / offline applications based on a HTML/CSS/JS layer to be displayed with Webview or a browser. The application can even run on cloud and on desktop environments with the same binary application.\n\n## Status\n\nCurrently, the project is not in active development anymore. There is [tauri](https://tauri.app/) (written in rust) that has similar goals and is much more advanced than nimview. Much more important - tauri is using webkit2 which supports state-of-the-art css and javascript. Nimview was still using webkit1 - which causes issues when using basic reactive Javascript on windows or when using modern css libraries. I will probably still review and merge PRs if you want to use nimview or if you think that those PRs are a good idea.\n\n## Features\n- Compile to small single executable binary that also includes the UI\n- No network port will be opened by Nimview in Desktop mode\n- Platforms: Windows, Linux, MacOS, Android, Cloud / Web\n- Use Nim, Python, C or C++ for your back-end\n- Use any HTML/CSS/JS based UI you want - Svelte, Vue, React, plain JS etc..\n- Desktop and Web mode\n- Simple automated back-end testing as backend functions just return strings\n- Integrated simple persistent storage\n- Immediately expose back-end functions to front-end with a simple command\n- Trigger front-end functions from backend \n\n## Table of Contents\n- [About](#about)\n- [Demo binary](#demo-binary)\n- [Youtube introduction](#youtube-introduction)\n- [Minimal Python Example](#minimal-python-example)\n- [Minimal Nim example](#minimal-nim-example)\n- [Javascript and HTML UI](#javascript-and-html-ui)\n- [Exchange data with UI](#exchange-data-with-ui)\n- [Development workflow](#development-workflow)\n- [Inline HTML to single binary](#inline-html-to-single-binary)\n- [Why Nim](#why-nim)\n- [Which JS framework for UI](#which-js-framework-for-ui)\n- [Nimview vs Electron or CEF](#nimview-vs-electron-or-cef)\n- [Nimview vs Eel or Neel](#nimview-vs-eel-or-neel)\n- [Difference to Flask](#difference-to-flask)\n- [Wails](#wails)\n- [CSRF and Security](#csrf-and-security)\n- [Multithreading](#multithreading)\n- [IE 11 or - \"Why is my page blank?](#multithreading)\n- [Limitations](#limitations)\n- [Using UI from existing web-applications](#using-ui-from-existing-web-applications)\n- [Software Requirements](#software-requirements)\n- [Documentation](#documnentation)\n\n\n## About\n\nThe target of this project was to have a simple, ultra lightweight cross platform, cross programming language UI layer for desktop, cloud and mobile applications. Nimview applications have just a few MB in static executable size and are targeted to be easy to write, easy to read, stable, secure and easy to test. The RAM consumption of basic Nimview applications is usually less than 20 MB on MS Windows.\n\nThis project uses [Webview](https://github.com/oskca/webview) to render Desktop \napplications and an integrated HttpServer for Development and Cloud. It doesn't use the latest version, as the latest version stopped working with file urls.\n\nNimview is an interface to interact with Nim/C/C++/Python code from UI Javascript in the same way for Webview desktop applications, web and mobile applications. It registers functions in the specific languages and also can mix Nim with any of the supported targets. \n\nTechnically, the UI layer will be completely HTML/CSS/JS based and the back-end should be using either Nim, C/C++ or Python code directly. \nNim mostly acts as a \"glue\" layer as it can create python and C libraries easily. As long as you write Nim code, you might integrate the code in C/C++, Python or even Android. \nThe final result should be a binary executable that runs on Linux, Windows or MacOS Desktop and even [Android](https://github.com/marcomq/examples/android). IOS wasn't tested yet.\n\nThe final application later doesn't require a webserver, but it is recommended to use the webserver mode during development or in debug mode.\nYou may also use the webserver for your cloud environemnt, but make sure to use additional authentication and a security reverse proxy when running on cloud.\n\nNode.js is recommended but not required if you want to build your Javascript UI layer with Svelte/Vue/React or the framework of your choice.\nThe HTTP server will run when compiling the application as \"debug\" by default, so you can use all your usual debugging and development tools in Chrome or Firefox. \nWebview makes it hard to debug Javascript - especially on Windows. You might use webview for production and testing, but you shouldn't focus Javascript UI development on Webview on windows.\n\nThis project is not intended to have any kind of forms, inputs or any additional helpers to create the UI. \nIf you need HTML generators or helpers, there are widely used open source frameworks available, for example Vue-Bootstrap (https://bootstrap-vue.org/).\n\n## Demo binary\nThere is a pre-build \"Todo-list\" demo application for windows x64 that uses a simple Svelte UI. \nTo make it work, you need to unzip everything before running the binaries. The zip contains two .exe files, \none desktop application \"appTodo\" and one HTTP server application \"httpTodo\" that opens a server on\nhttp://localhost:8000.\n- [demo.zip](https://github.com/marcomq/nimview/files/7077224/demo.zip)\nsha256sum df3d2595b9755b27b7034ce4970f44d3bca72544ce8915739062b4ba1d977158\n\nIf you want to build this demo from source, you need to run `nimble demo` on the\nNimview base folder.\n\n## Youtube introduction\n\nThere is some small \"Hello World\" tutorial for nimview on youtube:\nhttps://www.youtube.com/watch?v=OykIbez7Vfc\n\n## Minimal Python example\nThe project is available for python via `pip install nimview` and for nim via `nimble install nimview`. \nIf you just want to display some simple static HTML (or alternatively a jpg), you can run:\n\n```nim\nimport nimview\nnimview.start(\"hello_world.html\")\n```\n\nIf you want to actually trigger some server code from a button, you can do following in Python:\n\n```nim\nimport nimview\ndef echoAndModify(value): # One input value in the function signature is required\n    print (\"From front-end: \" + value)\n    return (value + \" appended\")\n\nnimview.add(\"echoAndModify\", echoAndModify)\nnimview.start(\"minimal_ui_sample/index.html\")\n```\n\nThe same in Nim:\n\n## Minimal Nim example\n```nim\nimport nimview\nnimview.add(\"echoAndModify\", proc (value: string): string =\n  echo \"From front-end: \" \u0026 value\n  result = \"'\" \u0026 value \u0026 \"' modified by back-end\")\nnimview.start()\n```\n\nNimview will automatically use \"../public/index.html\" as as entry page in debug mode\nand will try to load \"../dist/inlined.html\" in release mode. In release mode, the \ninlined.html entry point\nwill be compiled statically into the release binary. If there are no further dependencies,\nthe release binary can just run as single executable binary without further UI files.\nKeep in mind that when running in webserver mode, it will expose all files and subfolders that in the same directory as the index.html.\n\n## Javascript and HTML UI\nNimview offers an npm package \"npm install nimview\" which makes your life easier \non the front-end.\nIf you want to trigger back-end code from Javascript, you can do following\nasync callback:\n```js\nimport backend from \"nimview\"\nbackend.waitInit().then(() =\u003e {\n  backend.echoAndModify(\"test\").then((resp) =\u003e {console.log(resp)})\n})\n```\n`backend.waitInit` is only required if you want to immediately trigger some \nback-end function during initialization. Nimview takes a few milliseconds to \nload all functions from back-end to front-end.\nYou don't need this function if user action triggers a back-end call.\n\nKeep also in mind that the inlined.html is completely \"inlined\" for release mode and that any \"defer\" \nkeyword would not work for your script tags. So your javascript may be ready before\nthe DOM is ready for Jasascript. You may still trigger to load the \njavascript deferred when using \n```js\ndocument.addEventListener(\"DOMContentLoaded\", function(event) { \n```\nto init your javascript when the DOM is ready, for example in your \"main.js\" for Svelte or Vue.\n\n\n## Exchange data with UI\nNimview register functions to take up to 4 arguments. If you need more or if you have \nmore complex data, it is recommended to use Json to encode your values on the client. \nUse a parser on the back-end to read all values and send Json back to the client. By this, you have an unlimited amount of input and output\nparameter values.\nThis is easy when using python or Nim as back-end. This may also simplify automated unit testing, as you can store the specific strings as Json \nand only check specific Json values.\nNotice, that all registered functions return only strings, so the server will also just return a string value.\nIf you need Json, you need to parse this value in javascript manually, for example with JSON.parse().\nIn case you want to use C++ - don't write your own C++ Json parser. Feel free to use https://github.com/nlohmann/json. You might re-use it in other code locations.\n\nIt is also possible to call front-end functions directly from back-end by using\n`callJs`. You may trigger an `alert(\"Hello World!\")` on the frontend by \nusing following Nim code:\n```nim\n  nimview.callJs(\"alert\", \"Hello World!\")\n```\nin your back-end code. You may use as many parameters as you want.\nThis works directy for functions in the global js \"window\" namespace. If you need \nto call a local function, you need to register it first in javascript with \n`window.backend.mapFrontendFunction(\u003cfunctionName\u003e, function(parameter) {...})`.\nYou can then call it from back-end. \nKeep in mind to only use this to send visible information to the UI and not rely\nyour application workflow on this function. Otherwise, your application might \nbecome hard to test.\n\n## Development workflow\nYou need to compile the back-end and usually the front-end too, when using vue or svelte. While this seems unnecessary complicated in the beginning, \nyou will have the freedom to only restart the back-end if you have back-end changes and \nuse some autoreload feature of webpack (vue) and rollup (svelte) for the frontend.\n\nThe setup/install with Svelte after installing nim would be: \n- `nimble install nimview`\n- `npx degit marcomq/nimview/examples/svelte myProject`\n- `cd myProject`\n- `npm install`\n\nTo create a release version, just run\n- `npm run build`\n- `nim c -d:release --app:gui src/App.nim`\n\nBut if you want to change code easily, the development workflow would be:\n- start your back-end in debug mode with vs code or terminal, run: \n- `nim c -r -d:debug src/App.nim`\n- start your frontend npm in autoreload with VS-Code or terminal, run \n- `npm run dev`\n- open a browser with url http://localhost:5000 to see the current front-end code result that is served by Node.js\n- change your front-end code, the page will reload automatically\n- change your back-end code and re-run `nim c -r -d:debug src/App.nim` or restart the VS Code debugger\n- keep in mind that http://localhost:5000 is only a development url, the Javascript generated for production would be reachable by default at http://localhost:8000\n\nYou can also write simple integration tests with cypress using the debug (Webserver) mode.\nThis makes automated tests nearly as simple as for Electron.\nUnfortunately, Cypress doesn't support IE11 and Nimview doesn't support Edge/Chromium on Windows yet.\nBut thx to babel, there aren't many JS incompatibilities. \nAn Edge version of Nimview is already planned.\n\n## Inline HTML to single binary\nNimview doesn't automatically create a single executable that contains the user interface \nfor all possible scenarios. Nimview currently adds `../dist/inlined.html`\nto the binary - and only in release mode. This HTML file shouldn't contain any \nexternal dependencies like css, images \njavascript as these wouldn't be included in the executable binary.\nYou can use an inliner to inline your external dependencies. Check the svelte_todo exampple\nfor this. There is a \"npm build\" command in packages.js which calls an inliner to\nscan dist/index.html and write the output to `../dist/inlined.html`. For very small projects,\nyou may even use an inlined HTML file directly.\n\nKeep in mind that these inlined HTML files might also be hard to debug if they contain\njavascript - so you should still have some way to just open the un-inlined index.html file.\n\n## Components as diagram\n\n![nimview](https://user-images.githubusercontent.com/62469331/124002547-2ca26100-d9d6-11eb-955a-86954a016b69.png)\n\n\n### Why Nim\nNim is actually some great \"batteries included\" helper. It is similar readable as python, has some cool Json / HTTP Server / Webview modules \nbut creates plain C Code that can be compiled by gcc compilers to optimized machine code. \nYou can also include C/C++ code as the output of Nim is just plain C. Additionally, it can be compiled to a python library easily. \n(https://robert-mcdermott.gitlab.io/posts/speeding-up-python-with-nim/).\n\n### Which JS framework for UI\nThere are many JS frameworks to choose to create responsive user interfaces.\nSvelte will create the fastest and best readable front-end code. But it is completely up to you which framework you will choose, as Vue and React have much more plugins and add-ons.\n\nThere is an example for Vue + Bootstrap 4 in tests/vue and one for Svelte in tests/svelte.\nFor the Windows target, you need to choose a IE 11 compatible CSS library. Bootstrap 5 \nfor example isn't compatible with IE 11 anymore.\n\n### Nimview vs Electron or CEF\nElectron and CEF are great frameworks with a lot of useful utilities and both were an inspiration to this helper here. \nHowever, the output binary of electron or CEF is usually more than 100 MB and getting started with a new project without previous knowledge of Electron / CEF can also take some time. \nBoth CEF and Electron might be great for large Desktop projects that don't need to care about RAM + Disk or that require some additional custom window color,\ntask symbols or other features. \nBut setting up Electron / CEF applications and deploying them takes a lot of knowledge and time, which you can safe by using this helper here.\nThe binary output of Nimview is usually less than 2 MB. If you zip the binary, you even have less than 1 MB for a desktop application with UI. It also might just run in the Cloud as there is an included webserver \nYou might easily run the app in Docker. Getting started might just take some minutes and it will consume less RAM, \nless system resources and will start-up much quicker than an Electron or CEF App.\nYou might write the same Code and the same UI for your Cloud application as for your Desktop App.\nCypress integration tests might still work as Nimview has a webserver mode that can be used for testing. \n\n### Nimview vs Eel or Neel\nThere are another 2 cool similar frameworks: The very popular framework [eel](https://github.com/ChrisKnott/Eel) for python \nand its cousin [neel](https://github.com/Niminem/Neel) for nim. \nWhile the use case seems to be similar, there are some major differences: \n- With Nimview, you don't need a webserver running that might take requests from any other user on localhost as you use Webview in release mode. \nThis improves security as you don't need to worry about open ports or other attack vectors that need to be considered when running a webserver application. It also makes it easy to run multiple applications without having port conflicts. For some security scenarios, using a webserver - even on localhost - might be not an option at all. \nYou can use Nimview in suche a case, as you get a similar development experience but with less security concerns.\n- Nimview also includes a simple global token check in release mode that may be able to prevent most\n  CSRF attacks when the server is running on localhost.\n \n### Difference to Flask\n[Flask](https://github.com/pallets/flask) is probably the most popular python framework to create micro services and Nimview/AsyncHttpServer probably cannot compete with the easiness or with the amount of available plugins of Flask for simple python cloud applications. \nBut the use-case is different. While flask was desinged to serve HTML and have easy RESTful routes for \"get\" and \"post\", Nimview was just designed to trigger user events from ajax using \"post\". Nimview will not support server side template engines as flask does. The front-end code needs to care of routes and rendering.\n\nNimview can also create static binaries that can run in a minimal tiny Docker container that doesn't even need an installed python environment, as long as no python code is used. So you might create containers for your application that have just a few MB. Those deploy and startup much faster than Flask applications. Make sure to avoid building with Webview when creating binaries for Docker by compiling with `-d:useServer`, or you need to include GTK libraries in your container.\n\n### Wails\nAfter releasing the first 0.1.0 version of Nimview, I found out about [Wails](https://github.com/wailsapp/wails). And I found out that I nearly created a Wails clone. Just - Wails had some nice additional features \nthat Nimview didn't had. So - Wails became a big inspiration for Nimview \nVersion 0.2.0: \n- Compilation to a single static binary was added,\n- Multiple arguments for server functions were added and\n- Server functions are automatically exposed to the client when registered on server\nVersion 0.3.0: \n- Calling JS functions directly from back-end\n\nNimview currently \"borrows\" its current Webview code from Wails, as the wails community still performs fixes\non the old C header-only version of Webview.\n\nNimview still has a smaller code base and creates even smaller binaries. You also have classical languages \nfor your back-end as C, C++ or Python code - and you can mix those with Nim.\nAdditionally, Nimview supports Android for offline and online applications.\n\n### CSRF and Security\nNimview was made with security in mind. For the Webview `startDesktop` mode, no network ports are opened to display the UI. The webserver is mostly for debugging and development.  \nSo the application doesn't need to be checked for several common attack vectors\nof web-applications as long as Webview is used.\n\nHowever, if you create a web-application, you need perform most security mitigations by yourself, by middleware or by the javascript framework you are using. \nYou may check [owasp.org](owasp.org)\n\nFollowing CSRF protections are already included in Nimview: \n\nNimview stores 3 global random non-session tokens that renew each other every 60 seconds. A valid token is required for any Ajax request except \"getGlobalToken\". \nThe token is queried automatically with a \"getGlobalToken\" request when the application starts. If the token is missing or wrong, there is a \"403\" error for ajax requests.\n\nThis isn't a full CSRF protection, as the token isn't bound to a session and all \nusers that can read responses from localhost could also use this token to \nperform an attack (even if they may already send request directly to localhost).\nIf you add a \"Samesite\" directive for cookies, you might already prevent most common CSRF attack vectors.\nThe token check can also be disabled with `setUseGlobalToken(false)` for debugging, development,\nor in case that there is already a session-based CSRF mitigation used by middleware. \n\n### Multithreading\nNimview was initially planned to run single-threaded. But calling back-end functions stopped Webview from updating the DOM.\nTherefore, an additional Webview thread was added automatically that sends information back to the main thread with Nim Channels,\nif the application was compiled with the option `threads:on`. On linux, it is also recommended to use `gc:orc` to avoid issues\nwith the Nim garbage collector. You can still enforce to use Nimview to be completely single threaded if you compile with \n`-d:useWebviewSingleThreaded`. \nCheck the Nim manual on how to deal with multithreading and sharing data as multithreading is still complicate in Nim.\n\nYou may also use threads in Python or C++.\n\n### IE 11 or - \"Why is my page blank?\"\nNimview uses IE 11 on Windows. Unfortunately, IE 11 doesn't understand modern Javascript\nor ES6. Just writing modern Javascript will result in a blank white page. \nYou therefore need to transform your code with Babel or other tools. \nCheck the examples for this.\nIt might be possible to use Webview2 in future on Windows to get rid of IE 11, but this \nis depending on external Nim libraries that offer a wrapper for Webview. It wasn't tested yet,\nbut it may be possible to use GTK on Windows in case you really need to avoid IE 11.\nAt the time of writing, there is no simple and stable library supporting Webview 2 for Nim, \nand GTK on Windows was much more complicated as just using the IE 11 engine.\nThe examples mostly use `npm run dev` for daily development. These do not\ncompile for IE 11. If you use IE11, you need to run `npm run dev-ie`. This is not\nthe default, as the build takes much longer when using babel.\n\n### Using UI from existing web-applications\nFor Desktop applications, it is required to use relative file paths in all your HTML. The paths must point to a directory relative of the binary to the given index html file.\nIt is not possible to use a subdirectory of the index file. You can also not use a web URL as startpoint, as this must be an existing file.\nIt is also not recommended to load from an untrusted URL from any existing internet source, as this could easily cause a security breach.\nThe Desktop mode is using IE11 as platform, so there might be security issues when loading uncontrolled content from internet.\n\n## Software Requirements\n\n```\n- install nim (https://nim-lang.org/install.html)\n    avoid white-space in nim install folder name when using windows\n    add path by running nim \"finish\" in the nim install directory, so you have nimble available\n    restart or open new shell to have nimble available\n- linux: yum install gcc webkitgtk4-devel npm \u003cor:\u003e apt install gcc libwebkit2gtk-4.0-dev npm\n- windows: install node \u003e 12.19  (https://nodejs.org/en/download/)\n- nimble install nimview\n- (optional for C/C++ on Windows: install gcc / make sure that minGW is in your path)\n- npx degit marcomq/nimview/examples/xxx myProject\n```\n\n### Documentation\nA documentation is [here](https://htmlpreview.github.io/?https://github.com/marcomq/nimview/blob/master/docs/theindex.html)\n","funding_links":[],"categories":["👓 Alternatives to the [Electron.js](https://electronjs.org) ⚛","User Interface"],"sub_categories":["Nim","GUI"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcomq%2Fnimview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcomq%2Fnimview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcomq%2Fnimview/lists"}