Frontend - Tech Stack
Repository: finmars-platform/finmars-vue-portal
and finmars-platform/finmars-portal
and finmars-platform/finmars-workflow-portal
Overview
This document describes the technology stack used in the Vue Portal frontend.
Language
- JavaScript / TypeScript
Framework
- Vue 3 (main frontend framework)
- Angular.js (for
finmars-platform/finmars-portal
)
Build Tool
- Vite
State Management
- Pinia
Router
- Vue Router
UI / Styling
- CSS / SCSS
- TailwindCSS or UI component library (Naive UI / Element Plus / Vuetify)
API Layer
- HTTP Client: likely Axios
- Backend: Django REST Framework (from core), communication over REST/JSON
Authentication
- Keycloak (mandatory integration). Client library:
keycloak-js
Environment & Config
.env
files for environment variables (e.g.,VITE_*
) — exact names to be confirmed
Testing
- E2E Testing: Cypress / Playwright (separate repository)
Linting & Formatting
- ESLint, Prettier — rules and configs
CI/CD
- GitHub Actions (build and deploy). Build process based on Dockerfile
Containerization
- Docker (
Dockerfile
) - Docker Compose for local development — to be confirmed
Observability
- Logging and monitoring for the frontend — Sentry
License
- EUPL-1.2 (repository license)
finmars-vue-portal package.json
{
"private": true,
"scripts": {
"build": "nuxt build ",
"build:web-component": "vite build",
"dev": "nuxt --rootDir=./v/ dev -p=3000",
"dev-local": "NUXT_APP_BUILD_ASSETS_DIR=/realm00000/v/_nuxt/ API_HOST=http://0.0.0.0:8000 AUTH_HOST=http://0.0.0.0:8083/authorizer nuxt --rootDir=./v/ dev --host=0.0.0.0",
"start": "PORT=8080 node .output/server/index.mjs",
"generate": "nuxt generate",
"preview": "nuxt preview",
"test": "vitest",
"coverage": "vitest run --coverage"
},
"author": "Finmars SCSA",
"license": "EUPL-1.2",
"devDependencies": {
"@nuxt/test-utils": "^3.12.1",
"@nuxtjs/tailwindcss": "^6.12.1",
"@types/sanitize-html": "^2.13.0",
"@vitest/coverage-v8": "3.2.4",
"@vue/test-utils": "^2.4.5",
"consola": "^3.2.0",
"eslint": "^8.24.0",
"eslint-plugin-vue": "^9.6.0",
"happy-dom": "^17.0.0",
"nuxt": "^3.11.0",
"postcss-mixins": "^10.0.1",
"prettier": "3.3.3",
"sass": "1.85.1",
"unplugin-auto-import": "^0.16.6",
"unplugin-vue-components": "^0.25.1",
"vite-plugin-commonjs": "^0.10.1",
"vitest": "3.2.4"
},
"dependencies": {
"@chenfengyuan/vue-qrcode": "^2.0.0",
"@finmars/ui": "1.0.87",
"@formbricks/js": "1.1.2",
"@kyvg/vue3-notification": "^2.4.1",
"@pinia/nuxt": "^0.5.1",
"@vue/web-component-wrapper": "^1.3.0",
"ace-builds": "^1.36.2",
"chart.js": "^3.9.1",
"click-outside-vue3": "^4.0.1",
"dayjs": "^1.11.7",
"esbuild": "^0.25.5",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"floating-vue": "^5.2.2",
"grid-layout-plus": "^1.0.6",
"jquery": "^3.7.1",
"jsondiffpatch": "^0.6.0",
"jstree": "^3.3.17",
"keycloak-js": "^21.0.1",
"lodash": "^4.17.21",
"pdfjs-dist": "^4.0.269",
"pinia": "^2.0.24",
"qrcode": "^1.5.1",
"sanitize-html": "^2.13.1",
"swiper": "^10.0.4",
"vue": "^3.4.23",
"vue-matomo": "^4.2.0",
"vue3-ace-editor": "^2.2.2",
"vuedraggable": "^4.1.0"
}
}