meyi-vault-client
v1.0.2
Published
Self-hosted encrypted password manager — React UI plugin for MeyiConnect
Maintainers
Readme
vault-client
Self-hosted AES-256-GCM encrypted password manager — React UI plugin for MeyiConnect
Installation
npm install vault-clientMeyiConnect integration (3 steps)
Step 1 — Add the route file
Copy to frontend/src/routes/_authenticated/vault/$.tsx:
import { createFileRoute } from "@tanstack/react-router";
import { VaultApp, VaultProvider } from "vault-client";
import "vault-client/style.css";
import api from "@/services/api";
import { users } from "@/services/users";
function VaultRoute() {
return (
<VaultProvider
api={api}
getUsers={() => users.getAll().then((r) => r.data ?? r)}
>
<VaultApp />
</VaultProvider>
);
}
export const Route = createFileRoute("/_authenticated/vault/$")({
component: VaultRoute,
});Step 2 — Add to sidebar
In frontend/src/components/layout/data/sidebar-data.ts:
import { vaultNavItems } from 'vault-client'
import { FolderLock } from 'lucide-react'
// Add inside navGroups array:
{
title: 'Vault',
items: vaultNavItems.map(item => ({ ...item, icon: FolderLock })),
},Step 3 — Done
TanStack Router auto-discovers the new route file. Run npm run dev and
"Vaults" appears in the sidebar.
Standalone usage (any React app)
import { VaultProvider, VaultApp } from "vault-client";
import "vault-client/style.css";
import axios from "axios";
const api = axios.create({ baseURL: "https://your-api.example.com" });
function App() {
return (
<VaultProvider
api={api}
getUsers={async () => {
const res = await api.get("/api/v1/users");
return res.data.users;
}}
>
<VaultApp />
</VaultProvider>
);
}Composable exports
You can use individual pieces instead of the full VaultApp:
Pages (you manage routing)
import { VaultPage, GroupsPage, EntriesPage } from 'vault-client'
// VaultPage — lists all vaults
<VaultPage onNavigate={(to, vaultId) => router.push(`/vault/${vaultId}`)} />
// GroupsPage — lists domain groups inside a vault
<GroupsPage vaultId={vaultId} vaultName="Production" onNavigate={...} />
// EntriesPage — lists encrypted credentials inside a group
<EntriesPage vaultId={vaultId} groupId={groupId} onNavigate={...} />Hooks (bring your own UI)
import { useVaults, useEntries, useCreateGrant } from "vault-client";
function MyCustomVaultUI() {
const { data: vaults } = useVaults();
const { data: entries } = useEntries(groupId);
const createGrant = useCreateGrant();
// build your own UI
}Dialogs
import { EntryFormDialog, GrantAccessDialog } from 'vault-client'
<EntryFormDialog
open={open}
onOpenChange={setOpen}
groupId={groupId}
/>
<GrantAccessDialog
open={open}
onOpenChange={setOpen}
scope="vault"
scopeId={vaultId}
scopeLabel="Production"
/>VaultProvider props
| Prop | Type | Required | Default | Description |
| ---------- | ----------------------- | -------- | -------- | ---------------------------------------------- |
| api | AxiosInstance | ✅ | — | Host's axios instance (shares auth + base URL) |
| getUsers | () => Promise<User[]> | ✅ | — | Fetches users for grant picker |
| basePath | string | — | /vault | Base path for internal navigation |
What the package does NOT include
- Auth — uses the host's axios instance and req.user from the server
- Toast provider — uses
sonnerwhich must be mounted by the host - shadcn components — uses inline primitives; compatible with any Tailwind setup
