agentleFS
osmandapposmandapp/web/map/CLAUDE.md

web / map

CLAUDE.md63 starsChanged 2 months agoApache-2.0View on GitHub

Run from map/ unless stated otherwise. Tests live outside map/: Both have their own README.md and TESTS_STRUCTURE.md. The app has two independent parts: left menu and map. They share state only via React context — menu components must never call Leaflet directly, and map layers must never render menu UI. Left menu — panels in src/menu/. All panel components are always mounted simultaneously in MainMenu.js; visibility is toggled via display: block/none — panels are never unmounted. Switching panels triggers a…

The file

Show its rules and text

We split this CLAUDE.md into the rules it gives an agent

15 rules. About 0 are common, 6 are distinctive, and 9 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Run from map/ unless stated otherwise.

    line 5
  2. Distinctive:

    Always reuse. Never create a new component if one already exists.

    line 53
  3. Very specific:

    All user-visible strings must use useTranslation.

    line 57
  4. Very specific:

    If the key already exists in translation.json — use it as-is without web:.

    line 64
  5. Very specific:

    Never use setTimeout, setInterval, or clearInterval unless explicitly asked or there is absolutely no other way.

    line 76
  6. Distinctive:

    Before implementing anything — rendering, styling, data passing, formatting — search the codebase for an analogous place that already …

    line 80
  7. Very specific:

    Prefer CSS modules. Put styles in the corresponding .module.css file.

    line 106
  8. Very specific:

    Use sx={{...}} or style={{...}} only for dynamic runtime values (e.g.

    line 108
  9. Distinctive:

    Keep the number of props as small as possible.

    line 112
  10. Very specific:

    If a function is longer than 2 lines, add a blank line before return.

    line 116
  11. Distinctive:

    Do not create a local variable just to rename a context or prop value.

    line 124
  12. Very specific:

    Use ?. whenever a value may be null or undefined.

    line 128
  13. Distinctive:

    Before writing anything — check if it already exists.

    line 132
  14. Distinctive:

    Do not delete inline comments or block comments that already exist in code you are editing, even if they seem obvious or redundant.

    line 140
  15. Very specific:

    Avoid collapsing an if-statement to a single line when the condition contains more than one logical operator (&& or ||).

    line 144

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

OsmAnd Web — Agent Guide

Commands

Run from map/ unless stated otherwise.

CommandPurpose
yarn startdev server; start:local, start:local-routing, start:fallback switch the backend
yarn buildproduction build; build:staging for staging
yarn linteslint over src
yarn formatprettier — rewrites files
yarn testjest unit tests, delegates to tests/unit

Tests live outside map/:

  • tests/unit — jest: yarn test, test:watch, test:coverage.
  • tests/selenium — e2e against a running app: yarn test (localhost:3000), test:main (osmand.net), test:test (test.osmand.net).

Both have their own README.md and TESTS_STRUCTURE.md.

Project architecture

The app has two independent parts: left menu and map. They share state only via React context — menu components must never call Leaflet directly, and map layers must never render menu UI.

Left menu — panels in src/menu/. All panel components are always mounted simultaneously in MainMenu.js; visibility is toggled via display: block/none — panels are never unmounted. Switching panels triggers a React Router navigate(), but does not mount/unmount components. State is preserved through multiple layers: URL (pathname + search params, read via useLocation/useSearchParams), lastMenuUrlsRef (caches the last visited URL per panel so re-opening restores exact state), AppContext.pageParams (in-memory URL cache per menu type), and localStorage (visible tracks, sort preferences, map settings).

InfoBlock (src/infoblock/) — right-side detail panel that opens when the user selects a track, waypoint, POI, or shared file. Rendered inside MainMenu's persistent Drawer; width stored in ctx.infoBlockWidth. Content is determined by AppContext state: selectedGpxFile + currentObjectType → TrackContextMenu; selectedWpt → WptDetails; shareFile → ShareFileMenu. Visibility is controlled via showInfoBlock bool passed from GlobalFrame. Closing InfoBlock clears the relevant context fields and collapses the Drawer.

Map — Leaflet instance in src/map/. Multiple layers (TrackLayer, FavoriteLayer, PoiLayer, WeatherLayer, etc.). Map reacts to context changes, not to direct calls from menu.

Routing — all routes nested under /map. Defined in App.js. Pattern: /map/<section>/ with nested children. Example: /map/account/garmin.

Key directories

PathPurpose
src/context/Shared state: AppContext.js, LoginContext.js, FavoriteStorage.js, LocalTrackStorage.js
src/frame/components/Reusable UI components — always check here before creating new ones
src/manager/Business logic: GlobalManager.js (route constants, sizes), LoginManager.js, TracksManager.js, etc.
src/menu/Left menu panels per feature (tracks, favorites, search, navigation, weather, settings…)
src/map/Leaflet map, layers, markers
src/login/Auth UI, account, purchases, third-party integrations (Garmin)
src/dialogs/Modal dialogs and dialog.module.css

Contexts

  • AppContext — app-wide state: tracks, groups, visible layers, map settings
  • LoginContext — user, account info, login state; use INIT_LOGIN_STATE guard before rendering user-specific UI

Ready-made components (src/frame/components/)

Always reuse. Never create a new component if one already exists.

Translations

All user-visible strings must use useTranslation. Never hardcode display strings in JSX.

Key resolution order — always check in this order:

  1. src/resources/translations/en/translation.json — shared Android/iOS keys, no namespace prefix. Use as-is: t('shared_string_author').
  2. src/resources/translations/en/web-translation.json — web-only keys, use web: prefix: t('web:my_key').

If the key already exists in translation.json — use it as-is without web:. Only add a new key to web-translation.json if it does not exist in translation.json.

Route constants

Defined in src/manager/GlobalManager.js. Always import from there, never hardcode paths.


General Rules

No timers

Never use setTimeout, setInterval, or clearInterval unless explicitly asked or there is absolutely no other way. Always look for a lifecycle-based alternative first (e.g. useEffect on the right component, callbacks, React state).

Look for existing patterns first

Before implementing anything — rendering, styling, data passing, formatting — search the codebase for an analogous place that already solves the same problem. Use that pattern. Never invent a custom solution when one already exists.

Examples: HTML in translations → use <Trans>, bold text → <strong> in the translation key, dialog styles → copy from ImportFavoriteDialog, scroll layout → copy from LoginMenu.

Code Style

Component file structure

  1. Imports
  2. Constants
  3. Exported named functions — before export default function
  4. export default function ComponentName() — main component
  5. Private helpers — after the component

Hook order inside component

  1. Contexts (useContext)
  2. Translation (useTranslation)
  3. Hooks (useNavigate, useWindowSize, useLocation…)
  4. useState
  5. useCallback, useEffect, useMemo
  6. Derived values / handlers
  7. return

Styling

Prefer CSS modules. Put styles in the corresponding .module.css file.

Use sx={{...}} or style={{...}} only for dynamic runtime values (e.g. height from a hook).

Minimize props, maximize encapsulation

Keep the number of props as small as possible. If a component can get data from context or derive it internally — do so instead of passing it from outside. The simpler and more self-contained a component is, the better.

Blank line before return

If a function is longer than 2 lines, add a blank line before return.

No unnecessary arrow function wrappers

Pass functions directly instead of wrapping them in arrow functions.

No unnecessary variable aliases

Do not create a local variable just to rename a context or prop value. Use the source directly.

Optional chaining

Use ?. whenever a value may be null or undefined. Avoid &&-chains for property access.

Avoid code duplication

Before writing anything — check if it already exists. Extract shared logic into modules, pass data that's already fetched instead of re-fetching it.

No unnecessary refactoring

When asked to make a focused change — fix a bug, add a feature, rename something — do exactly that and nothing else. Do not restructure surrounding code, rename unrelated variables, reorder logic, or "clean up" things that weren't part of the request. Unrelated changes make diffs harder to review and can introduce bugs.

Never remove existing comments

Do not delete inline comments or block comments that already exist in code you are editing, even if they seem obvious or redundant. Comments represent the author's intent and are part of the code's documentation.

No 1-liner if-statements with multiple conditions

Avoid collapsing an if-statement to a single line when the condition contains more than one logical operator (&& or ||). Always use a block body in that case. Single-condition 1-liners are fine: if (!group) return;.

refs — last resort

Use useRef / ref only when the problem cannot be solved any other way. Always look for a solution via state, context, props, or derived values first. A ref is acceptable only when all other options are unsuitable (e.g. direct DOM node access, storing a value without triggering a re-render).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.