{"id":51388829,"url":"https://github.com/usini/bete","last_synced_at":"2026-07-03T22:00:34.816Z","repository":{"id":366888722,"uuid":"1278329512","full_name":"usini/bete","owner":"usini","description":"Mindmap pense-bete pixel art - site statique","archived":false,"fork":false,"pushed_at":"2026-07-01T15:50:18.000Z","size":649,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-01T17:28:09.442Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://usini.github.io/bete/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/usini.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-23T17:29:27.000Z","updated_at":"2026-07-01T15:50:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/usini/bete","commit_stats":null,"previous_names":["remisarrailh/pensebete","usini/bete"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/usini/bete","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usini%2Fbete","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usini%2Fbete/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usini%2Fbete/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usini%2Fbete/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/usini","download_url":"https://codeload.github.com/usini/bete/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usini%2Fbete/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35102741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-03T02:00:05.635Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-03T22:00:16.544Z","updated_at":"2026-07-03T22:00:34.785Z","avatar_url":"https://github.com/usini.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bete\n\nPixel-art mindmap. 100% static site, zero dependencies, zero build step.\n\n## Run locally\n\nES modules don't work over `file://`, so you need a small server:\n\n```bash\npython -m http.server 8000\n# then open http://localhost:8000\n```\n\n## Deploy to GitHub Pages\n\n1. Push the repo to GitHub.\n2. `Settings → Pages → Build and deployment → Source: Deploy from a branch`.\n3. Branch `main`, folder `/ (root)`. The site is served as-is.\n\nFor a custom domain: `Settings → Pages → Custom domain`, and a `CNAME` file\n(containing your domain) appears at the repo root — replace it or delete it\nif you fork the project to host it under a different domain.\n\n## Language\n\nThe app is available in French and English. It guesses the language from\nthe browser on first visit; your choice in Settings → Language is then\nremembered and always takes priority. Adding a new language is a small,\nself-contained change in `js/i18n.js` (one dictionary object + one list\nentry) — see the comments there.\n\n## Usage\n\n- **Right-click**: radial menu (create rectangle/sign/circle/hexagon/liaison, color, text, delete, export/import).\n- **Sign**: a larger rectangle with a wood texture, for titles/panels.\n- **Deleting** an object makes it **explode into pieces** (animation, synced with clients).\n- **Wheel**: zoom · **drag the background**: pan the view.\n- **Drag a rectangle**: elastic movement.\n- **Drag a circle/hexagon's edge**: resize · **drag its inside**: move it.\n- **Double-click**: edit the text (Escape to confirm). On an **image rectangle**: opens the image full-size.\n- **Drag-and-drop an image** (or **Ctrl-V** an image from the clipboard): onto a rectangle to put it inside, onto empty space to create an image rectangle (\"Remove image\" to take it out). The image is always shown **in full**; the rectangle keeps a roughly constant size.\n- **Link** (radial menu on a rectangle): attaches a URL; an ↗ badge appears and a **click** opens the link in a new tab.\n- **Delete**: erases the selected element.\n- **Ctrl-C / Ctrl-V**: copy-paste the selected element (pasted at the mouse position).\n- A rectangle whose center is inside a circle/hexagon takes its color.\n\n### Hexagons \u0026 links\n\nA **hexagon** (e.g. \"Today\") aggregates **links** to rectangles stored elsewhere.\nDrag a rectangle (from a circle) into a hexagon: a **link** (dashed border) is\ncreated, the original goes back to its place. The link keeps the **source\ncircle's color** and mirrors its text/image; renaming or deleting the source\nupdates (or removes) the link. Links can be freely placed inside the hexagon.\n\n### Sync across devices (P2P)\n\nTo copy your board from one device to another (e.g. desktop → phone):\n\n1. On the **source** device (HOST): radial menu → **\"+ Liaison\"**. A QR code block appears.\n2. On the other device (CLIENT): **scan the QR** (or open the link — clicking the block copies it).\n3. Once connected, the client's board is replaced by the host's, then both stay **synced live, in both directions**, as long as the host's window stays open.\n\n**Synced**: the content (text, image, color, description, links, creations/deletions) and the **objects' positions** — but the latter only **on drop** (not during the drag), and the other screen **animates** it. **The camera stays independent**: each screen keeps its own zoom/framing (e.g. one screen zoomed out, another zoomed into a circle). If the same element is edited simultaneously, **the host wins**.\n\n**Encrypted P2P connection** (WebRTC via PeerJS); only connection identifiers go through the signaling broker, the content travels directly between the two browsers. The PeerJS / QR libs are loaded on demand (CDN), the app stays dependency-free at rest. Images and voice memos are stored locally (IndexedDB) and only transit once per peer, never through the broker.\n\n**Permanent host (optional)**: to keep sync available even with all browsers closed, you can run a small Node server on a Raspberry Pi that acts as a permanent host — see [`server/`](server/README.md). The app doesn't need any modification: devices connect to it via `?peer=\u003cpi-id\u003e`.\n\nThe liaison id is **stable** (remembered): refreshing the host's page and recreating the liaison gives back **the same link/QR**. On a network drop, the host automatically reconnects to the broker (same id) and clients retry the connection — no need to rescan. If the link leaks, **\"New link\"** (liaison block menu) regenerates an id: the old URL becomes invalid, the board is preserved.\n\nPrivacy-wise: content travels over encrypted WebRTC (DTLS), directly between peers in the normal case; if a direct connection isn't possible, it's relayed (encrypted) by PeerJS's TURN servers. The broker only ever sees connection identifiers.\n\n### Mobile / touch\n\n- **Interaction locked by default** (so a block isn't accidentally moved): only panning (1 finger) and zooming (pinch) work. **Long-press** then only offers **\"Enable\"**. Once enabled, the standard radial menu comes back (with **\"Lock\"** to re-lock it).\n- **1 finger**: drags the background (pan) or, once enabled, moves an element.\n- **2 fingers**: pinch to zoom.\n- **Long-press**: radial menu · **double-tap**: edit / view the image (interaction enabled).\n\nAutomatic save in the browser (localStorage). JSON export/import via the radial menu.\n\n## Open a board from a URL\n\nAdding `?file=\u003curl\u003e` to the address loads that JSON instead of localStorage, without overwriting your personal board:\n\n```\nhttps://your-instance.example/?file=https://example.com/board.json\n```\n\nThe file must be accessible over CORS (same origin, raw.githubusercontent.com, gist…). A relative path also works: `?file=boards/demo.json`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusini%2Fbete","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fusini%2Fbete","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusini%2Fbete/lists"}