meilisearch-ui is a browser-side admin panel that never proxies your keys
😎 Open-source, pretty, simple and fast ⚡ Meilisearch admin dashboard UI for managing your meilisearch instances 🕹
At a glance
- What is it?
- meilisearch-ui is a React and Vite admin dashboard for Meilisearch instances that talks to the search engine directly from the browser, so the instance configuration and the API key live in the client rather than on a server you operate.
- Who is it for?
- meilisearch-ui is a good fit for a team that wants a familiar dashboard for a Meilisearch instance on a trusted internal network, and for anyone who wants to host the panel on Vercel or as a static bundle rather than run a server side application.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 45 days ago.
- What is it written in?
- Mainly TypeScript, 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
Every request goes from the browser straight to the search engine
meilisearch-ui is described as an open-source admin dashboard UI for managing Meilisearch instances, and its architecture is the first thing to understand. The README states that this app uses the Meilisearch official JS client to call your Meilisearch instance, and later repeats the point in more detail: this app is a pure client-side SPA, all requests go directly from the browser to your Meilisearch instance, and data is stored inside your browser.
That single decision shapes everything else. There is no backend of this project holding your instance credentials, so there is no credential store to compromise on the dashboard side, and there is no proxy hop between the browser and the search engine. The panel is a static bundle that a browser downloads and runs.
The feature list is what you would expect from an admin panel for a search engine: indexes CRUD, searching documents, documents management, index settings, and multiple instances management. The last one is worth pausing on, because with the credentials held in the browser, switching between instances means the browser holds several of them at once. Multiple instances management is convenient for a developer working across several projects, and it is also the feature that most raises the stakes of storing an admin key in local browser storage.
The stack behind it is a React 18 application built with Vite, using the meilisearch JavaScript client at version 0.49.0, TanStack Router and Query for routing and data fetching, i18next for translations in English and Chinese, and CodeMirror for editing JSON documents. The component layer pulls in Arco Design, Mantine, NextUI and Semi UI.
CORS configuration is the step everyone misses
Before the dashboard can do anything, your Meilisearch instance has to allow the dashboard origin. The README makes this an explicit warning: remember update CORS settings in your instance server for this ui domain before using, because the panel uses the official JS client to call the instance with API calls and the server has to be configured manually.
The example given is an nginx configuration snippet:
# ... other configurations
add_header Access-Control-Allow-Origin "your.meilisearch-ui.domain.com";
# ... other configurationsYou add the domain where you host the panel to the CORS list of the instance, and the panel can talk to it. The failure mode without this step is quiet in the sense that the page loads and the instance list stays empty, with the browser refusing the cross origin request.
There is a security dimension to that header, and the README does not soften it. The panel expects a key with real privileges, since it manages indexes and settings. If you allow an origin that anyone can host, and the key is stored in a browser, the combination matters more than either part alone. The advice further down the README is to deploy the panel in a trusted internal network environment, and that is the operative constraint for this whole architecture.
The same header applies to the online demo. The project runs a live demo deployed on Vercel at meilisearch-ui.vercel.app, so if you point a demo instance at that origin you are allowing a third-party hosted domain to talk to your search engine, and the README's instruction to add your deployment domain to the CORS list means the origin you add must be one you control.
Docker on port 24900 is the shortest path to a working panel
The Docker path is two commands, and the image is published on Docker Hub as eyeix/meilisearch-ui:
docker pull eyeix/meilisearch-ui:latest
docker run -d --restart=on-failure:5 --name="meilisearch-ui" -p <your-port>:24900 eyeix/meilisearch-ui:latestThe container listens on 24900 internally, so you map it to a port of your choosing on the host, and the restart policy keeps the panel up across daemon restarts. The Dockerfile behind the image is straightforward: a node:22 base, a working directory of /opt/meilisearch-ui, pnpm pinned to major version 10 to keep Docker builds reproducible, the dependencies installed with pnpm install, port 24900 exposed, NODE_ENV set to prod, and the entrypoint set to a shell script at ./scripts/cmd.sh.
That entrypoint detail explains the docker-entrypoint.d/ directory in the repository and the nginx template files. The repository carries nginx.root.conf.template and nginx.basepath.conf.template, which suggests the container serves the static bundle through nginx rather than running a Node server in the foreground, and the entrypoint script is what selects and patches the configuration at start time.
The base path is configurable through an environment variable. If you need the panel served from a subdirectory rather than the root of a domain, set BASE_PATH:
docker run -d --restart=on-failure:5 --name="meilisearch-ui" -p <your-port>:24900 -e BASE_PATH="/meilisearch-ui" eyeix/meilisearch-ui:latestThe README links the discussion of base path support to an issue in the tracker, which is worth reading before you rely on it, since the behaviour of a base path under nginx is exactly the kind of thing that differs between a root deployment and a subdirectory deployment.
Singleton mode puts the API key in the browser bundle
Singleton mode is for teams that want the panel wired to one fixed instance, so a user opens it and starts working without choosing a target. The README describes it as an easy way to integrate the tool with your own apps, and it can be enabled with three environment variables:
docker run -d --restart=on-failure:5 \
--name="meilisearch-ui" \
-p <your-port>:24900 \
-e SINGLETON_MODE=true \
-e SINGLETON_HOST=your-meilisearch-host \
-e SINGLETON_API_KEY=your-api-key \
eyeix/meilisearch-ui:latestThe supported variables are SINGLETON_MODE, SINGLETON_HOST and SINGLETON_API_KEY, and the singleton instance has no configurable index or id.
Now the caveats, which are stated at length and deserve to be read carefully.
The environment variables are only baked into the static bundle at build time, and all requests then go directly from the browser to the instance. That has two direct consequences. The instance host must be reachable from the browser, so a Docker internal hostname such as http://meilisearch:7700 will not work unless your browser can resolve it; use a host-reachable address such as http://<server-ip>:7700 or a reverse-proxied domain. And the security note is explicit: any singleton mode relevant environment variables exposed this way will eventually appear in the client package, so you should try to avoid using this method, and when you do use singleton mode packaging you need to carefully judge the network environment in which you deploy the application, with a trusted internal network recommended.
So singleton mode is a convenience with a known cost. The API key ends up in a file any browser can download. The README's own recommendation is to avoid the method, which is a clearer statement than most projects make about a similar trade-off.
The lite image is smaller and drops singleton mode
The project ships a second image variant, and the README explains why. Due to functions such as adapting custom paths, the main image size becomes a burden for some users, so if you only need the basic functionality of the application you can use the lite variant image, which contains only the necessary constructs and is very small compared to the main image.
The variant is built from a separate Dockerfile, Dockerfile-lite, that sits next to the main one in the repository, and the exact tags are listed on Docker Hub.
The feature cost is stated in one line: lite images do not support singleton mode. Everything else in the feature list, indexes CRUD, document search, documents management, index settings, multiple instances management and the browser side storage of data, stays. The multiple instance management capability is what makes the lite image coherent, since it does not depend on the pre-configured target.
That makes the choice straightforward in practice. If you deploy the panel behind a subdomain with a few engineers picking their own instance, the lite image is enough and keeps the footprint small. If the whole point is the drop-in single instance setup with a baked key, you need the main image, and you accept the image size and the client-side exposure of the key.
One more deployment route exists for teams that do not want to run containers at all. The project is deployed on Vercel, with a one-click deploy button in the README, and the repository also carries a vercel.json and a netlify.toml, so a static host is a first class target rather than an afterthought.
Building from source means VITE_ prefixed variables in .env.local
For anything beyond the published images, the README documents a source build in four steps.
Clone the repository, shallow:
git clone [email protected]:eyeix/meilisearch-ui.git --depth=1Move into the root directory of the repository:
cd meilisearch-uiInstall the dependencies with pnpm:
pnpm installThen create a.env.local file at the root of the repository with the singleton configuration:
VITE_SINGLETON_MODE=true
VITE_SINGLETON_HOST=your-meilisearch-host
VITE_SINGLETON_API_KEY=your-api-keyThe VITE_ prefix is what distinguishes this from the Docker path. Vite exposes variables prefixed this way to the client bundle at build time, which is exactly the mechanism behind the singleton mode warning. A.env.local file is local only, and the README points to an issue about the security risk of that file, so treat it as a secret that must not be committed and must not be used with a production admin key.
The build scripts in package.json show what a production build involves. The default build runs vite build and then node scripts/post-build.js, and there is a build:safe variant that runs tsc first, so type errors fail the build rather than producing a bundle that misbehaves at runtime. A separate build:docker script runs only vite build, and development is vite with the start script as an alias. Linting is handled by Biome, and the repository has a biome.json alongside tailwind.config.cjs and uno.config.ts.
Apache-2.0 licensed, with release tags and an unstable main branch
The project is licensed under Apache-2.0, with the licence file at the root of the repository. For a dashboard that may be deployed inside a company network, the terms are permissive, and the obligation that matters practically is the notice and licence file travelling with any redistribution of the code or the built image.
The versioning is the part to understand before you deploy. The README warns in an important note that the main branch may be unstable or unavailable during development, and asks you to use a release rather than the main branch to obtain a stable version of the app. The visible tags are v0.15.1 on 2026-02-04, v0.15.2 and v0.15.3 both on 2026-09-02, so the project versions its releases and keeps a stable line separately from main.
That warning shapes the docker command in the README, which pulls the latest tag. If you want a reproducible deployment, pin an explicit version tag instead of latest, and remember that the lite and main images have to match the release you pin. The repository automates releases with release-please, configured in release-please-config.json and .release-please-manifest.json, and it keeps a CHANGELOG.md at the root.
The last push was on 2026-09-08, so work is still landing after the v0.15.3 tag. If you are evaluating the project, read the CHANGELOG.md between the tag you plan to use and the tip of main to see what changed. The repository also carries AGENTS.md, CLAUDE.md and a .agentdocs/ directory, which are the files to read if you plan to have an automated assistant work on the codebase rather than just deploy it.
Editorial conclusion
meilisearch-ui is a good fit for a team that wants a familiar dashboard for a Meilisearch instance on a trusted internal network, and for anyone who wants to host the panel on Vercel or as a static bundle rather than run a server side application. It is the wrong choice for an instance exposed to the internet, because the panel is a pure client-side SPA and any singleton mode variables baked into the bundle are readable by anyone who opens the browser, and it is the wrong choice for small screens, since the README warns that the responsive design is incomplete and recommends desktop use. Before deploying, add the dashboard origin to the instance CORS list, decide between the main and lite image knowing that lite drops singleton mode, and pin a release tag rather than tracking main, which the README warns may be unstable.
Frequently asked questions
How do I run meilisearch-ui with Docker?
Pull the image and run it, mapping the container port 24900 to a host port of your choice: docker run -d --restart=on-failure:5 --name="meilisearch-ui" -p <your-port>:24900 eyeix/meilisearch-ui:latest. You must also add the dashboard origin to the CORS list of your Meilisearch instance.
Why does meilisearch-ui show no instances or fail to load data?
The app is a pure client-side SPA that calls your Meilisearch instance directly from the browser, so the instance has to allow the dashboard origin in its CORS settings. The README asks you to add your ui panel deployment domain to the instance cors list.
What is singleton mode in meilisearch-ui and what is the risk?
Singleton mode points the panel at one fixed instance using the SINGLETON_MODE, SINGLETON_HOST and SINGLETON_API_KEY environment variables. The README warns that these variables are baked into the static bundle at build time and will appear in the client package, so it recommends deploying in a trusted internal network and trying to avoid the method.
What is the difference between the meilisearch-ui lite image and the main image?
The lite variant is much smaller because it contains only the necessary constructs, and it exists because the main image size becomes a burden for some users. Lite images do not support singleton mode; the basic functionality stays available.
Can I deploy meilisearch-ui under a subpath?
Yes. Set the BASE_PATH environment variable to the path you want to serve from, for example /meilisearch-ui, and the repository ships nginx.basepath.conf.template alongside nginx.root.conf.template for that case.
Does meilisearch-ui work on mobile devices?
Not fully. The README warns that the app has not achieved responsive design totally and advises using it on desktop for a better experience.
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/eyeix-meilisearch-ui)Was this useful?