MistralMapper is a React and Vite application with a Node and Express API for generating, reviewing, and storing mappings between WildApricot invoice data and QuickBooks product and class data. PostgreSQL stores user accounts and login sessions, while MongoDB stores approved mapping records.
The application supports account-based test data discovery, a guided 5-step mapping workflow, Mistral-powered mapping suggestions, manual confirmation, and MongoDB persistence for approved mappings.
The main UI lives in src/components/MappingConfiguration.jsx and orchestrates this sequence:
- Load WildApricot invoice JSON from a file upload or account-specific endpoint.
- Load QuickBooks product and class JSON from a file upload or account-specific endpoint.
- Build a prompt and request suggested mappings from Mistral through a server-side route.
- Let the user confirm or adjust the generated mapping.
- Store the confirmed mapping in MongoDB.
The project has two runtime parts:
- Frontend: React app served by Vite.
- Backend: Express API in
server/index.jsfor MongoDB access, health checks, and optional server-side Mistral access.
During local development, Vite also exposes two development-only middleware routes:
/dev-api/test-accounts/dev-api/mistral-mapping
These routes let the frontend discover account folders and call Mistral without exposing the API key in browser code.
Key folders and files:
src/components/MappingConfiguration.jsx: main workflow UI.src/services/mappingSequence.js: orchestration for loading data, generating prompts, calling mapping endpoints, and saving results.server/index.js: Express API for health, history, latest mappings, persistence, and backend Mistral calls.vite.config.js: Vite configuration plus development middleware for account discovery and Mistral proxying.public/: static assets and test data folders.dist/: production build output generated by Vite.
Copy .env.example to .env for local development.
Required variables:
MISTRAL_API_KEY: used by the dev server and backend to call Mistral.MONGODB_URI: MongoDB connection string for mapping persistence.DATABASE_URL: PostgreSQL connection string for users and sessions.SESSION_SECRET: random secret with at least 32 bytes of entropy.
Optional variables:
PORT: backend port. Default is4000.ALLOWED_ORIGIN: allowed frontend origin for CORS. Default ishttp://localhost:5173.MONGODB_DB: Mongo database name. Default isMistralMapper.MONGODB_COLLECTION: Mongo collection name. Default isMappings.MONGO_API_KEY: optional bearer token required byPOST /api/mappingswhen configured.DATABASE_POOL_SIZE: PostgreSQL connection pool size. Default is10.
Do not expose Mistral credentials to the frontend bundle.
Use this pattern:
- Store
MISTRAL_API_KEYonly in server-side environment configuration. - Let the frontend call
/dev-api/mistral-mappingin development or/api/mistral-mappingin backend-driven deployments. - Do not rely on
VITE_MISTRAL_API_KEYin production.
Also make sure:
.envis not committed..env.examplecontains placeholders only.- Production secrets are injected by the hosting platform or secret manager.
Install dependencies:
npm installPrepare the PostgreSQL authentication tables after configuring DATABASE_URL:
npm run db:migrateRun frontend and backend together:
npm run dev:fullOr run them separately:
npm run devnpm run dev:serverDefault local URLs:
- Frontend:
http://localhost:5173 - Backend:
http://localhost:4000
Create a production build:
npm run buildPreview the production build locally:
npm run previewPOST /api/auth/register: creates an organization and user, then starts a session.POST /api/auth/login: verifies the password and starts a session.GET /api/auth/me: returns the currently signed-in user ornull.POST /api/auth/logout: destroys the current session.POST /api/auth/forgot-password: sends a single-use password reset link.POST /api/auth/reset-password: verifies the reset token and stores a new password hash.
Passwords are hashed with Argon2id before they are stored. Browser sessions use an HTTP-only cookie and are stored in PostgreSQL.
Password reset emails use Resend. Configure RESEND_API_KEY, RESET_EMAIL_FROM, and APP_URL to deliver email. During local development without a Resend key, the backend prints the reset link to its terminal instead of sending it.
Returns backend and MongoDB status.
Example response:
{
"ok": true,
"mongodb": "connected",
"database": "MistralMapper",
"collection": "Mappings"
}Calls Mistral from the backend using the server-side API key.
Example request body:
{
"model": "mistral-large-latest",
"prompt": "Map WA order types to QuickBooks products and classes.",
"wildApricotItems": ["Adult Membership", "Student Membership"],
"quickBooksProducts": [
{ "Id": "101", "Name": "Adult Member", "Classification": "Membership" }
],
"quickBooksClasses": ["Membership"],
"isAccountant": false
}Returns the most recent stored mappings used as context for repeat runs.
Supported query parameters:
accountId: optional numeric account identifier.isAccountant:trueorfalse.
Returns the latest n mappings for a specific account.
Supported query parameters:
accountId: required numeric account identifier.n: optional number of records to return. Default is10, capped at100.
Example:
/api/mappings/latest?accountId=1001&n=25
Stores a confirmed mapping in MongoDB.
Example request body:
{
"accountId": 1001,
"isAccountant": false,
"prompt": "Map WA order types to QB products and classes.",
"sourceData": { "items": [] },
"targetData": { "QueryResponse": {} },
"mapping": [
{
"WAFieldName": "Adult Membership",
"QBProduct": "Adult Member",
"QBProductId": "101",
"QBClassification": "Membership"
}
]
}Example success response:
{
"ok": true,
"insertedId": "...",
"storedAt": "..."
}In development, the Vite middleware scans public/ and public/test-data/ for folders whose names end in digits. Those digits are treated as the account ID.
Example folder names:
Account 1001Customer account 2004
For each matched folder, the middleware attempts to locate:
- a WildApricot JSON file
- a QuickBooks JSON file
These are then exposed through /dev-api/test-accounts so the UI can populate the account dropdown and auto-bind source and target endpoints.
The UI supports:
- Switching between file-based and endpoint-based JSON inputs.
- Loading account-specific data automatically from discovered folders.
- Parsing QuickBooks products from
QueryResponse.Itemdata. - Preselecting product and class values from returned mapping data.
- Adding custom product and class entries during confirmation.
Saved mapping records include fields such as:
accountIdisAccountantpromptsourceDatatargetDatamappingcreatedAt
An index is created on createdAt to support recent-history queries.
Check:
MISTRAL_API_KEYis present in the environment.- The frontend is calling the dev or backend route, not Mistral directly.
- The development server was restarted after env changes.
Check:
MONGODB_URIis valid.- Your MongoDB server or Atlas cluster is reachable.
- The backend logs for connection or TLS errors.
Check:
- Test-data folders exist under
public/orpublic/test-data/. - Folder names end with digits so an account ID can be parsed.
- Each folder contains JSON files for WildApricot and QuickBooks data.
For production:
- Build the frontend with
npm run build. - Serve
dist/from your static hosting layer. - Run the Express server separately for API and MongoDB operations.
- Inject secrets through platform-managed environment variables.
- Keep Mistral and MongoDB credentials server-side only.