Maple Research is the existing Maple client, built with React, Vite, and Tauri. It runs as a web application and as native desktop/mobile applications, and uses OpenSecret for confidential authentication, inference, conversations, and related APIs.
Research chat uses the TypeScript Maple SDK with the Responses and
Conversations APIs on web, desktop, and mobile; native OAuth uses the Rust Maple
SDK through Tauri. The local OpenAI-compatible proxy is a separate user-facing
desktop service. Agent work lives in Maple Work
(apps/maple-agent/). On desktop, users with the
agent_mode flag see a sidebar Chat | Agent switch; its Agent page only points
them to Maple Work.
The Maple SDK source and its upstream Git history live under
sdk/. Research selects published TypeScript and Rust
versions independently in its manifests and lockfiles, with local links
supported during development. See the
SDK consumer version policy.
The proxy source and its upstream history live under
proxy/; desktop Maple consumes that in-tree crate too.
The source directory name does not change the shipped Maple application identity. Commands and code paths below are relative to the monorepo root, unless a command explicitly changes directory. Shared Nix, Just, CI, and release entry points remain there.
Choose the environment and login path first. Preserve generated workspace configuration and lifecycle ownership; the standalone examples below apply when those resources are unowned.
The supported development environment is the Nix flake. It pins Bun, Rust, platform tools, and native dependencies used by the repository.
nix develop --no-update-lock-file
./setup-hooks.sh
just install
test -e apps/maple-research/frontend/.env.local || cp apps/maple-research/frontend/.env.example apps/maple-research/frontend/.env.localThis creates apps/maple-research/frontend/.env.local only when it is absent. Never overwrite an
existing file: it may be externally managed or contain checkout-specific
backend and application configuration. Inspect its source before changing its
values.
The common recipes below assume the active Nix shell. For an independent call,
prefix a recipe with nix develop --no-update-lock-file -c.
For hosted Dev browser work, use the
explicit profile launch and account procedure;
it preserves an existing Local .env.local. The standalone configuration and
runtime recipes below consume the environment already configured for them.
For unowned standalone configuration, select the intended OpenSecret API in
the ignored apps/maple-research/frontend/.env.local:
VITE_OPEN_SECRET_API_URL=http://127.0.0.1:3000Use the project/client ID belonging to that backend; a managed workspace may
provide its own value. The public Maple client ID is present in .env.example. All VITE_*
values are shipped to the client and must never contain secrets.
Start the runtime you intend to exercise:
just dev # Browser/web development only
just desktop-dev # Tauri desktop and native featuresjust desktop-dev is preferred over a raw bun tauri dev: it provisions the
pinned ONNX Runtime and applies a local Tauri configuration overlay when one is
present.
For a separately installed desktop package targeting the standalone Auth Dev site,
use the Research Dev desktop package, built with
nix run --no-update-lock-file .#research-dev-desktop on Linux or macOS. It has its
own bundle identity, callback scheme, storage, and disabled updater; the ordinary
Local workflow and iOS Dev TestFlight profile remain separate.
apps/maple-research/frontend/.env.example documents Maple's public configuration surface:
VITE_OPEN_SECRET_API_URLselects the required OpenSecret backend.VITE_OPEN_SECRET_PCR_ENVIRONMENTselects the matching PCR0 trust roots; it defaults toproduction, so hosted development enclaves must setdevelopmentexplicitly.VITE_CLIENT_IDoverrides Maple's public project ID when developing against another OpenSecret project.VITE_OS_FLAGS_BASE_URLselects an optional feature-flags API.VITE_MAPLE_BILLING_API_URLselects an optional billing API.VITE_FORCE_FEATURE_FLAGSis a local preview override, not authorization.- Native OAuth also selects a browser auth origin from the app variant and
VITE_MAPLE_DEV_AUTH_ORIGIN; selecting a local API alone does not make OAuth local. Follow the auth/environment contract.
Flags and billing are independent clients; configure their dev or production API URLs for the environment being tested. A working OpenSecret chat does not prove billing- or flag-gated behavior. Provider credentials and administrative API keys belong on their servers, never in Maple.
To use a local backend, follow
OpenSecret's setup guide
from services/opensecret/, including its SQL migration step. Keep the default
frontend origin unless you also intend to change and validate OAuth/verification
callback handling.
Run commands from the repository root:
just # List recipes
just install # Install frontend dependencies
just dev # Web dev server
just desktop-dev # Desktop dev application
just desktop-build-debug-overlay # Unsigned debug package with local overlay
just build # Local web build
just format # Format frontend source
just lint # Lint frontend source
just rust-check # Check the Tauri Rust crate
just rust-lint # Optional strict Clippy diagnostic; not current Research CI/hook
just clean-local # Clean only this checkout's Cargo artifactsBun commands run from apps/maple-research/frontend/; Cargo commands run from
apps/maple-research/frontend/src-tauri/. Raw cargo clean can remove a shared Nix Cargo build
directory, so use just clean-local.
For routine Local validation use a supported encrypted password/account fixture and verify effective API/project and login before dependent behavior. Use hosted Dev only deliberately with a valid Dev account; provider/native OAuth is a separate intentional integration scenario. Debug/simulator does not imply Local.
Use the checked-in CI entry points rather than reconstructing them:
# Frozen install, formatting, ESLint, typecheck, and Bun tests
nix develop --no-update-lock-file .#ci -c ./scripts/ci/frontend.sh
# Locked all-target Rust tests
nix develop --no-update-lock-file .#ci -c ./scripts/ci/rust.sh
# PR-configured web artifact
MAPLE_WEB_ENVIRONMENT=pr nix develop --no-update-lock-file .#ci -c ./scripts/ci/web.sh
# Nix/toolchain/workflow metadata; not application tests
nix flake check --no-update-lock-fileThere is no general checked-in browser, packaged-app, or React-to-Tauri-command
integration harness. Unit tests and package builds do not prove GUI, native,
backend, billing, flags, or IPC integration. A privileged IPC change therefore
requires a manual smoke test through the exact desktop application and native
effect. For change-specific test selection and a repeatable evidence format,
use .agents/skills/validate-maple/.
PR build scripts deliberately ignore local .env* files and compile fixed PR
endpoints. They prove PR packaging, not integration with the backend configured
in apps/maple-research/frontend/.env.local. To smoke an exact desktop development application
against that configured backend, use just desktop-dev, record the active
Tauri overlay, endpoint configuration, executable and application identifier,
then exercise the user entry point through Tauri IPC to the native result.
Desktop recipes provision ONNX Runtime automatically:
just desktop-build # Standard application identity
just desktop-build-debug # Standard application identity
just desktop-build-debug-overlay # Requires .local/tauri-workspace.jsonOnly the overlay recipe applies .local/tauri-workspace.json while packaging.
Use it when a checkout-specific bundle identity is part of the smoke test.
Linux desktop builds require the system libraries supplied by the Nix shell. For an already-built binary in a headless display environment, WebKit may need:
WEBKIT_DISABLE_COMPOSITING_MODE=1 \
WEBKIT_DISABLE_DMABUF_RENDERER=1 \
DISPLAY=:0 ./apps/maple-research/frontend/src-tauri/target/debug/mapleApple development uses the pinned Apple shell and repository recipes:
just ios-build-onnxruntime
just ios-dev
just ios-dev-sim 'iPhone 16 Pro'
just ios-dev-device 'Your iPhone'just ios-fix-arch mutates the generated Xcode project. Inspect and either
commit or deliberately restore generated changes; do not hide them from Git.
Android development is supported from x86_64 Linux; the .#android shell is
not exposed on macOS:
nix develop --no-update-lock-file .#android -c just android-buildAndroid is consumption-only: accounts can use existing subscriptions, team
access, API credits and subscription passes acquired elsewhere. The app does
not offer subscription checkout, credit purchases, paid upgrades, or billing
portal links that can start purchases. /pricing shows plan information without
mounting legacy checkout effects, including after an old selected_plan callback.
Payment API helpers also reject Android calls before requesting a checkout or
portal. This is an Android platform rule for all users, independent of app review
or server version flags; web, desktop and iOS keep their existing purchase flows.
Android may explain that plans are managed on the website without linking to checkout. Subscription support remains available by email. Google explicitly allows consumption-only apps and purchase communication outside the app.
The CI scripts under scripts/ci/ are the authority for PR and release-shaped
platform builds. Some are platform-specific, remove build outputs or
node_modules, and deliberately ignore local .env* files in favor of fixed
PR/release endpoints; read a script before running it locally.
docs/development-contracts.mdrecords runtime placement, native-command, security, and concurrency contracts.docs/pdf-ocr.mdcovers the local PDF/OCR pipeline.AGENTS.mddefines Research placement and runtime standards; the root guide defines shared repository policy..agents/skills/contains task-specific development, validation, security, and release procedures.
apps/maple-research/frontend/src/routeTree.gen.ts and native platform projects contain generated
content. Use their generators and review the resulting diff rather than editing
generated output opportunistically.
Release preparation and publication are production actions. A push to
master that changes classified Maple app inputs starts production-shaped
signed workflows and can upload an iOS build to TestFlight; creating a GitHub
Release always starts the complete release pipeline, attaches the four native
maple-proxy archives to that same release, and starts downstream publication.
Do not use either as routine validation.
Use .agents/skills/release-maple/ for version parity, tag safety, workflow
monitoring, artifact verification, and explicit store handoff. Do not use the
legacy just release recipe to create an unreviewed local tag.
When the OpenSecret enclave changes, update and review the corresponding
PCR0_DEV_VALUES or PCR0_VALUES in
apps/maple-research/frontend/src/config/openSecretClientConfig.ts as part of the
attestation compatibility change.
Version changes update:
apps/maple-research/frontend/package.jsonapps/maple-research/frontend/src-tauri/tauri.conf.jsonapps/maple-research/frontend/src-tauri/Cargo.tomlapps/maple-research/frontend/src-tauri/gen/apple/project.ymlapps/maple-research/frontend/src-tauri/gen/apple/maple_iOS/Info.plistapps/maple-research/frontend/src-tauri/Cargo.lock
Keep changes focused, follow the nearest established patterns, add regression coverage at the owning layer, and report exactly which checks and runtime paths you exercised. Security-sensitive changes should distinguish source-confirmed facts from deployment assumptions and live-environment observations.
Before opening a pull request, run the applicable full gates above and inspect
git diff --check. See AGENTS.md for the complete change and review standard.