FreqUI: the Vue interface for a self-hosted Freqtrade bot
Freqtrade UI - Frontend for Freqtrade
At a glance
- What is it?
- FreqUI is the Vue and PrimeVue front end for Freqtrade, the trading bot. It is bundled into Freqtrade itself, so most users never install it, but it can also run as a standalone container, and its build is a two stage Docker image that ends in nginx serving static files.
- Who is it for?
- Adopt FreqUI only if you are running Freqtrade and want to work on its interface, because for ordinary use the UI ships inside the bot and there is nothing to deploy. Do not treat the standalone container as a product surface, since it still requires a correctly configured Freqtrade bot and a CORS setup that allows the UI origin.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Vue, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The interface half of a trading bot
FreqUI is the Freqtrade UI, a frontend for the Freqtrade trading bot, built with Vue.js and PrimeVue. The primary language in the repository listing is Vue, and the current stack is Vue 3 with vue-router 5, Pinia for state, and PrimeVue having been replaced by the Nuxt UI and reka-ui component packages.
The single most important fact for most readers is in the run section. Using FreqUI requires Freqtrade to be set up and running, and in newer versions, 2021.2 and newer, FreqUI is built into Freqtrade, so a manual setup of FreqUI is no longer necessary unless you want to modify it. The end-user setup instructions live in the Freqtrade API documentation rather than here.
That makes this repository a development project rather than a deployment one. The audience is developers working on the interface, and the alternative path, a standalone container, exists for the case where you are running a Freqtrade instance somewhere else and want the UI on a different host.
The licence is GPL-3.0, the project lives at github.com/freqtrade/frequi, and the repository topics name the pairing: freqtrade, freqtrade-ui, trading, trading-bot, vue and vuejs. The release numbers are independent of the bot's, so a FreqUI version does not tell you which Freqtrade version it expects.
The standalone container and the CORS tax
Running FreqUI on its own is a single command, because a pre-built image is published:
docker compose up -dThat starts a container with FreqUI running on port 3000, defaulting to the latest version of the UI, and you can update to the newest build with docker compose pull. The compose file in the repository is minimal, one service named frequi using the image freqtradeorg/frequi:latest, restart unless-stopped, with the port mapping 3000 to 80. The local build lines are commented out, so the file is a consumer setup by default, with a note on how to build the image yourself instead.
The paragraph after the command is the part people miss. This is a standalone version of FreqUI and it will still require a correctly configured Freqtrade bot, and you will need to configure CORS in Freqtrade correctly to allow FreqUI to connect to the API.
That is a real operational tax. The browser origin has to be allowed by the bot, the bot has to be reachable from wherever the UI is running, and the two configurations have to agree. The Freqtrade documentation has a section on CORS and the README links straight to it.
The value of the standalone mode is therefore narrow. It makes sense when the bot is on a different machine, when you want the UI behind its own domain or authentication, or when you are running a modified build. For a single-user setup where the bot already serves its own UI, it is one more moving part.
The developer loop needs a running bot and a matching origin
Setting up the project for development has one requirement that catches newcomers out: Freqtrade has to be running on the same host with the API enabled under localhost:8080.
The toolchain is pnpm, and the three commands are the standard ones:
pnpm install
pnpm run dev
pnpm run buildThe dev script compiles and hot-reloads, the build script compiles and minifies for production, and there is a lint script that lints and fixes files. The dev server runs on port 3000, and the README notes that the webpack proxy port can be changed in vue.config.js, or you can connect directly to the API, which is the recommended option.
The CORS requirement is spelled out with an operational detail that makes the difference between working and not working. You need CORS for Freqtrade configured correctly based on the Freqtrade documentation, and most likely the correct entry will be http://localhost:3000 or http://127.0.0.1:3000, but the URL must match the URL you use to access FreqUI. Ports can vary, so check the URL you are using.
That last sentence is the crux. The CORS entry is not the port the UI listens on, it is the origin in the browser's address bar, so a proxied setup on a different port, or an access via a hostname instead of an IP, will fail with a CORS error until the allow list is updated. The documentation tells you to check the URL you are using rather than assuming the default.
For developers who prefer a container, the devcontainer setup is documented too. Building the image with a compose file in the .devcontainer directory, then entering the web service container with docker-compose exec web /bin/bash and running pnpm run dev, gives a hot-reloading window against a bot running alongside.
What the dependency list says about the interface
The package manifest is a good map of what the UI actually contains, and it is worth reading as a description of the product.
The charting and table layer is the largest part. echarts with vue-echarts handles the charts, which for a trading bot means the profit curves and the per-pair charts, and @tanstack/vue-table is the data grid, which is what the trade list and the pair list are built from. @noction/vue-draggable-grid and sortablejs are for the drag and drop configuration screens, so a dashboard layout can be rearranged, and deepmerge is the helper for combining the saved layout with the defaults.
The component layer is @nuxt/ui with reka-ui underneath, plus @iconify-json/mdi for the Material Design icons. The presence of favico.js is a small human detail: the favicon reflects the bot's state, so a trader can see at a glance from the browser tab whether the bot is running.
The state and data layer is Pinia with pinia-plugin-persistedstate, so the interface survives a page reload with your layout and settings intact, and ofetch for HTTP. The date handling is unusually thorough for a dashboard: date-fns with date-fns-tz for time zones, and @internationalized/date for locale-aware date handling.
The utility layer is @vueuse/core and its integrations, humanize-duration for turning durations into readable text, and vue-router 5 for navigation. The interesting choice here is that the component stack is not PrimeVue any more, even though the README still names it, which suggests the migration to the Nuxt UI and reka-ui packages happened after that line was written.
Unit tests in Vitest, end to end across three browser engines
The test setup covers both levels, and the end to end part is the more interesting one.
Unit tests run on Vitest, with a test:unit script and happy-dom as the DOM environment in the development dependencies, and the Vue Test Utils package for component tests. The type checking is separate, with a typecheck script that runs vue-tsc in build mode with no emit, and the lint scripts run ESLint over src, tests and e2e, with a lint-ci variant that does not fix, which is the one that belongs in CI.
End to end tests run on Playwright, and the scripts are per engine. test:e2e runs the whole suite, and then there are test:e2e-chromium, test:e2e-msedge and test:e2e-firefox for the individual projects. The Playwright configuration lives in playwright.config.ts and the tests in the e2e/ directory.
Running the suite against Microsoft Edge as well as Chromium and Firefox is unusual and sensible. Firefox is a different engine from Chromium, so a layout or API difference in the charting or the table components shows up there first.
The repository also has a Dockerfile, a docker/ directory, a.devcontainer/ directory, a.browserslistrc for the browser targets, a.prettierrc.json, an eslint.config.mjs, three tsconfig files splitting the app and node configurations, a vite.config.ts, a vercel.json and a nginx.conf.
The production image ends in nginx
The Dockerfile is short and it is the clearest statement of what the built artefact is.
FROM node:26.10.0-alpine AS ui-builder
RUN mkdir /app \
&& corepack enable
WORKDIR /app
COPY package.json pnpm-lock.yaml /app/
RUN apk add --update --no-cache g++ make git \
&& pnpm install --frozen-lockfile \
&& apk del g++ make
COPY . /app
RUN pnpm run build
FROM nginx:1.31.6-alpine
COPY --from=ui-builder /app/dist /etc/nginx/html
COPY --from=ui-builder /app/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx"]Two stages, and the second one contains no Node at all. The builder installs the dependencies with a frozen lockfile, builds the assets with pnpm run build, and then the runtime stage is nginx serving the dist directory and the project's own nginx.conf. The final image is a static file server.
The dependency caching is deliberate. Only package.json and pnpm-lock.yaml are copied before the install, so a change to a source file does not invalidate the dependency layer, and the native build tools, g++ and make are installed for the install step and removed again in the same layer.
The fact that the runtime is nginx rather than a Node server is worth noting for anyone deploying this. There is no application server to patch, no Node runtime to keep current, and the security surface is a web server serving files. The cost is that everything in the interface, including the API configuration, is client side, so the browser talks to the Freqtrade API directly and CORS is the mechanism that makes that work.
The vercel.json and the.browserslistrc in the repository root indicate that a static hosting deployment is also a supported path for the built assets.
Maintenance and where this project sits
The release history is regular. Version 3.1.1 was tagged on 2026-07-31, 3.1.2 on 2026-08-30 and 3.1.3 on 2026-09-29, and the last push was on 2026-10-14. The repository is not archived, and the CI workflow badge for the main branch is the check to look at before you pull.
The monthly cadence is what you would expect for a user interface that has to keep pace with a bot's REST API. The API is versioned on the Freqtrade side, and every time it changes, the interface has to catch up, which is the real maintenance driver for this repository.
The division of labour is worth stating plainly if you are deciding where to look. Freqtrade itself is a separate project, and this repository holds only the interface. The API documentation for the bot is where the endpoint contract lives, and the end-user setup instructions for the bundled UI are there too, which is a deliberate choice, since a UI that is a setting inside the bot should be documented with the bot.
For anyone evaluating this project as a component, the practical questions are narrow. Is the Freqtrade API stable enough for you to build on, does the CORS configuration fit your deployment, and are you prepared to track a Vue 3 and Vite stack that is actively churning through its component libraries? The dependency versions in the manifest, with reka-ui, Nuxt UI and Tailwind 4 all on current majors, suggest the project is keeping up with the ecosystem rather than coasting on an old lockfile.
Editorial conclusion
Adopt FreqUI only if you are running Freqtrade and want to work on its interface, because for ordinary use the UI ships inside the bot and there is nothing to deploy. Do not treat the standalone container as a product surface, since it still requires a correctly configured Freqtrade bot and a CORS setup that allows the UI origin. Before you start, run the bot with the API enabled on localhost:8080, decide whether to use the development proxy or connect directly to the API as the documentation recommends, and remember that the container publishes port 3000 mapped to nginx on port 80 inside.
Frequently asked questions
Do I need to install FreqUI separately from Freqtrade?
No. Since version 2021.2 FreqUI is built into Freqtrade, and manual setup is only needed if you want to modify the interface. The end-user setup instructions are in the Freqtrade API documentation.
How do I run FreqUI as a standalone container?
Run docker compose up -d, which starts the freqtradeorg/frequi:latest image with port 3000 published, and use docker compose pull to update it. It still needs a correctly configured Freqtrade bot, and CORS in Freqtrade must allow the UI origin to reach the API.
How do I set up FreqUI for development?
You need Freqtrade running on the same host with the API enabled under localhost:8080. Then run pnpm install and pnpm run dev for a hot-reloading server, with CORS in Freqtrade configured to allow the URL you actually use to access the UI, which is usually http://localhost:3000.
What does the FreqUI production image contain?
Two Docker stages. The builder uses node:26.10.0-alpine, installs dependencies with a frozen pnpm lockfile and runs pnpm run build, and the runtime stage is nginx:1.31.6-alpine serving the dist directory and the project's nginx.conf on port 80, with no Node runtime in the final image.
How is FreqUI tested?
Unit tests run on Vitest with happy-dom, and end to end tests run on Playwright with separate scripts for the chromium, msedge and firefox projects. Type checking uses vue-tsc and linting uses ESLint over src, tests and e2e.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/freqtrade-frequi)Was this useful?