{"id":13469540,"url":"https://github.com/tinyplex/tinybase","last_synced_at":"2026-04-18T07:06:39.031Z","repository":{"id":36987170,"uuid":"443220240","full_name":"tinyplex/tinybase","owner":"tinyplex","description":"A reactive data store \u0026 sync engine.","archived":false,"fork":false,"pushed_at":"2026-03-31T06:14:27.000Z","size":384167,"stargazers_count":4987,"open_issues_count":42,"forks_count":124,"subscribers_count":37,"default_branch":"main","last_synced_at":"2026-03-31T06:59:44.515Z","etag":null,"topics":["data","javascript","react","reactive","typescript"],"latest_commit_sha":null,"homepage":"https://tinybase.org","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tinyplex.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support/tinybase-demo-server/.dockerignore","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"agents.md","dco":null,"cla":null},"funding":{"github":"jamesgpearce"}},"created_at":"2021-12-31T01:06:00.000Z","updated_at":"2026-03-31T04:45:20.000Z","dependencies_parsed_at":"2024-01-09T18:56:07.616Z","dependency_job_id":"d3d753f1-33a1-428c-9a0f-7a1656be2590","html_url":"https://github.com/tinyplex/tinybase","commit_stats":{"total_commits":437,"total_committers":3,"mean_commits":"145.66666666666666","dds":0.004576659038901587,"last_synced_commit":"77c95062049b0e22143f12a2418c256d45a07fcb"},"previous_names":[],"tags_count":335,"template":false,"template_full_name":null,"purl":"pkg:github/tinyplex/tinybase","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinyplex%2Ftinybase","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinyplex%2Ftinybase/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinyplex%2Ftinybase/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinyplex%2Ftinybase/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tinyplex","download_url":"https://codeload.github.com/tinyplex/tinybase/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tinyplex%2Ftinybase/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31427387,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T02:22:46.605Z","status":"ssl_error","status_checked_at":"2026-04-05T02:22:33.263Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["data","javascript","react","reactive","typescript"],"created_at":"2024-07-31T15:01:44.074Z","updated_at":"2026-04-05T07:03:36.651Z","avatar_url":"https://github.com/tinyplex.png","language":"TypeScript","readme":"\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/react.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/indexeddb.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/browser.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/cloudflare.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/postgresql.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/pglite.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/sqlite.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/bun.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/expo.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/electric.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/turso.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/powersync.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/partykit.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/yjs.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/crsqlite.png\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/automerge.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/zod.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/typebox.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/valibot.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/arktype.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/yup.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/effect.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge\u0026amp;logo=GitHub\u0026amp;logoColor=%23fff\u0026amp;label=GitHub\u0026amp;labelColor=%23d81b60\u0026amp;color=%23333\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/badge/Bluesky-Follow-blue?style=for-the-badge\u0026amp;logo=bluesky\u0026amp;logoColor=%23fff\u0026amp;color=%23333\u0026amp;labelColor=%230285FF\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/badge/%2F%20Twitter-Follow-blue?style=for-the-badge\u0026amp;logo=x\u0026amp;logoColor=%23fff\u0026amp;color=%23333\u0026amp;labelColor=%23000\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/discord/1027918215323590676?style=for-the-badge\u0026amp;logo=discord\u0026amp;logoColor=%23fff\u0026amp;label=Discord\u0026amp;labelColor=%233131e8\u0026amp;color=%23333\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge\u0026amp;logo=GitHub\u0026amp;logoColor=%23fff\u0026amp;label=Ideas\u0026amp;labelColor=%23d81b60\u0026amp;color=%23333\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge\u0026amp;logo=GitHub\u0026amp;logoColor=%23fff\u0026amp;label=Issues\u0026amp;labelColor=%23d81b60\u0026amp;color=%23333\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge\u0026amp;logo=Vitest\u0026amp;logoColor=%23fff\u0026amp;color=%23333\u0026amp;labelColor=%2387c305\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://img.shields.io/npm/v/tinybase?style=for-the-badge\u0026amp;logo=npm\u0026amp;logoColor=%23fff\u0026amp;labelColor=%23bd0005\u0026amp;color=%23333\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/ui-react-dom.webp\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/inspector.webp\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/fastrepl.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/expo.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/dylmye.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/ComputelessComputer.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/cancelself.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/cpojer.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/beekeeb.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/WonderPanda.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/arpitBhalla.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/behrends.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/betomoedano.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/brentvatne.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/byCedric.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/circadian-risk.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/cubecull.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/erwinkn.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/ezra-en.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/feychenie.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/flaming-codes.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/fostertheweb.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/Giulio987.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/hi-ogawa.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/itsdevcoffee.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/jbolda.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/Kayoo-asso.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/kotofurumiya.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/Kudo.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/learn-anything.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/lluc.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/marksteve.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/miking-the-viking.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/mjamesderocher.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/mouktardev.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/nickmessing.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/nikitavoloboev.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/nkzw-tech.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/palerdot.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/PorcoRosso85.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/primodiumxyz.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/shaneosullivan.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/sudo-self.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/SuperSonicHub1.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/threepointone.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/uptonking.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/ViktorZhurbin.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://github.com/wilkerlucio.png?size=48\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://synclets.org/favicon.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinywidgets.org/favicon.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinytick.org/favicon.svg?asImg\"\u003e\u003clink rel=\"preload\" as=\"image\" href=\"https://tinybase.org/youtube.webp\"\u003e\u003csection id=\"hero\"\u003e\u003ch2 id=\"a-reactive-data-store-sync-engine\"\u003eA \u003cem\u003ereactive\u003c/em\u003e data store \u0026amp; \u003cspan\u003e\u003cem\u003esync\u003c/em\u003e engine\u003c/span\u003e\u003c/h2\u003e\u003c/section\u003e\u003cp\u003e\u003ca href=\"https://tinybase.org/guides/releases/#v7-3\"\u003e\u003cem\u003eNEW!\u003c/em\u003e v7.3 release\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\u003cspan id=\"one-with\"\u003e\u0026quot;The one with state hooks!\u0026quot;\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003ca class=\"start\" href=\"https://tinybase.org/guides/the-basics/getting-started/\"\u003eGet started\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://tinybase.org/demos/\"\u003eTry the demos\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003eRead the docs\u003c/a\u003e\u003c/p\u003e\u003chr\u003e\u003csection\u003e\u003ch2 id=\"let-s-build-local-first-apps\"\u003eLet\u0026#x27;s build \u003cem\u003elocal-first\u003c/em\u003e apps\u003c/h2\u003e\u003cp\u003eCreate a todo list, a chat app, a drawing tool, or a tic-tac-toe game - with sync \u0026amp; persistence! - in less than 60 seconds.\u003c/p\u003e\u003c/section\u003e\n\n```bash\n\u003e npm create tinybase@latest\n\n📦 Creating your project...\n```\n\n\u003chr\u003e\u003csection\u003e\u003ch2 id=\"it-s-reactive\"\u003eIt\u0026#x27;s \u003cem\u003eReactive\u003c/em\u003e\u003c/h2\u003e\u003cp\u003eTinyBase lets you \u003ca href=\"#register-granular-listeners\"\u003elisten to changes\u003c/a\u003e made to any part of your data. This means your app will be fast, since you only spend rendering cycles on things that change. The optional \u003ca href=\"#call-hooks-to-bind-to-data\"\u003ebindings to React\u003c/a\u003e and \u003ca href=\"#pre-built-reactive-components\"\u003epre-built components\u003c/a\u003e let you easily build fully reactive UIs on top of TinyBase. You even get a built-in \u003ca href=\"#set-checkpoints-for-an-undo-stack\"\u003eundo stack\u003c/a\u003e, and \u003ca href=\"#an-inspector-for-your-data\"\u003edeveloper tools\u003c/a\u003e!\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2 id=\"it-s-database-like\"\u003eIt\u0026#x27;s \u003cem\u003eDatabase-Like\u003c/em\u003e\u003c/h2\u003e\u003cp\u003eConsumer app? Enterprise app? Or even a game? Model \u003ca href=\"#start-with-a-simple-key-value-store\"\u003ekey-value data\u003c/a\u003e and \u003ca href=\"#level-up-to-use-tabular-data\"\u003etabular data\u003c/a\u003e with optional typed \u003ca href=\"#apply-schemas-to-tables-values\"\u003eschematization\u003c/a\u003e, whatever its data structures. There are built-in \u003ca href=\"#create-indexes-for-fast-lookups\"\u003eindexing\u003c/a\u003e, \u003ca href=\"#define-metrics-and-aggregations\"\u003emetric aggregation\u003c/a\u003e, and tabular \u003ca href=\"#model-table-relationships\"\u003erelationships\u003c/a\u003e APIs - and a powerful \u003ca href=\"#build-complex-queries-with-tinyql\"\u003equery engine\u003c/a\u003e to select, join, filter, and group data (reactively!) without SQL.\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2 id=\"it-synchronizes\"\u003eIt \u003cem\u003eSynchronizes\u003c/em\u003e\u003c/h2\u003e\u003cp\u003eTinyBase has \u003ca href=\"#synchronize-between-devices\"\u003enative CRDT\u003c/a\u003e support, meaning that you can deterministically \u003ca href=\"https://tinybase.org/guides/synchronization/\"\u003esynchronize\u003c/a\u003e and merge data across multiple sources, clients, and servers. And although TinyBase is an in-memory data store, you can easily \u003ca href=\"#persist-to-storage-databases-more\"\u003epersist\u003c/a\u003e your data to file, \u003ca href=\"https://tinybase.org/api/persister-browser\"\u003ebrowser storage\u003c/a\u003e, \u003ca href=\"https://tinybase.org/api/persister-indexed-db\"\u003eIndexedDB\u003c/a\u003e, \u003ca href=\"https://tinybase.org/guides/persistence/database-persistence/\"\u003eSQLite or PostgreSQL databases\u003c/a\u003e, and \u003ca href=\"https://tinybase.org/guides/persistence/third-party-crdt-persistence/\"\u003emore\u003c/a\u003e.\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2 id=\"it-s-built-for-a-local-first-world\"\u003eIt\u0026#x27;s Built For A \u003cem\u003eLocal-First\u003c/em\u003e World\u003c/h2\u003e\u003cp\u003eTinyBase works anywhere that JavaScript does, but it\u0026#x27;s especially great for local-first apps: where data is stored locally on the user\u0026#x27;s device and that can be run offline. It\u0026#x27;s tiny by name, tiny by nature: just \u003ca href=\"#did-we-say-tiny\"\u003e5.4kB - 12.1kB\u003c/a\u003e and with no dependencies - yet \u003ca href=\"#well-tested-and-documented\"\u003e100% tested\u003c/a\u003e, \u003ca href=\"https://tinybase.org/guides/the-basics/getting-started/\"\u003efully documented\u003c/a\u003e, and of course, \u003ca href=\"https://github.com/tinyplex/tinybase\"\u003eopen source\u003c/a\u003e!\u003c/p\u003e\u003c/section\u003e\u003chr\u003e\u003csection id=\"friends\"\u003e\u003ch2 id=\"tinybase-works-great-on-its-own-but-also-plays-well-with-friends\"\u003eTinyBase works great on its own, but also plays well with friends.\u003c/h2\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/building-uis/getting-started-with-ui-react\"\u003e\u003cimg src=\"https://tinybase.org/react.svg?asImg\" width=\"48\"\u003e React\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister\"\u003e\u003cimg src=\"https://tinybase.org/indexeddb.svg?asImg\" width=\"48\"\u003e IndexedDB\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/persister-browser\"\u003e\u003cimg src=\"https://tinybase.org/browser.svg?asImg\" width=\"48\"\u003e OPFS\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/integrations/cloudflare-durable-objects\"\u003e\u003cimg src=\"https://tinybase.org/cloudflare.svg?asImg\" width=\"48\"\u003e Cloudflare\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/postgresql.svg?asImg\" width=\"48\"\u003e PostgreSQL\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/pglite.svg?asImg\" width=\"48\"\u003e PGlite\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/sqlite.svg?asImg\" width=\"48\"\u003e SQLite\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/bun.svg?asImg\" width=\"48\"\u003e Bun SQLite\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/expo.svg?asImg\" width=\"48\"\u003e Expo SQLite\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/electric.svg?asImg\" width=\"48\"\u003e ElectricSQL\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/turso.svg?asImg\" width=\"48\"\u003e Turso\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence\"\u003e\u003cimg src=\"https://tinybase.org/powersync.svg?asImg\" width=\"48\"\u003e PowerSync\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/persister-partykit-client\"\u003e\u003cimg src=\"https://tinybase.org/partykit.svg?asImg\" width=\"48\"\u003e PartyKit\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister\"\u003e\u003cimg src=\"https://tinybase.org/yjs.svg?asImg\" width=\"48\"\u003e YJS\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/persister-cr-sqlite-wasm\"\u003e\u003cimg src=\"https://tinybase.org/crsqlite.png\" width=\"48\"\u003e CR-SQLite\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/persister-automerge\"\u003e\u003cimg src=\"https://tinybase.org/automerge.svg?asImg\" width=\"48\"\u003e Automerge\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/schematizer-zod/functions/creation/createzodschematizer\"\u003e\u003cimg src=\"https://tinybase.org/zod.svg?asImg\" width=\"48\"\u003e Zod\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/schematizer-typebox/functions/creation/createtypeboxschematizer\"\u003e\u003cimg src=\"https://tinybase.org/typebox.svg?asImg\" width=\"48\"\u003e TypeBox\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/schematizer-valibot/functions/creation/createvalibotschematizer\"\u003e\u003cimg src=\"https://tinybase.org/valibot.svg?asImg\" width=\"48\"\u003e Valibot\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/schematizer-arktype/functions/creation/createarktypeschematizer\"\u003e\u003cimg src=\"https://tinybase.org/arktype.svg?asImg\" width=\"48\"\u003e ArkType\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/schematizer-yup/functions/creation/createyupschematizer\"\u003e\u003cimg src=\"https://tinybase.org/yup.svg?asImg\" width=\"48\"\u003e Yup\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href=\"https://tinybase.org/api/schematizer-effect/functions/creation/createeffectschematizer\"\u003e\u003cimg src=\"https://tinybase.org/effect.svg?asImg\" width=\"48\"\u003e Effect\u003c/a\u003e\u003c/div\u003e\u003cp\u003e(Baffled by all these logos? Check out our \u003ca href=\"https://tinybase.org/guides/the-basics/architectural-options\"\u003earchitectural options\u003c/a\u003e guide to make sense of it all!)\u003c/p\u003e\u003c/section\u003e\u003chr\u003e\u003csection id=\"follow\"\u003e\u003ca href=\"https://github.com/tinyplex/tinybase\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge\u0026amp;logo=GitHub\u0026amp;logoColor=%23fff\u0026amp;label=GitHub\u0026amp;labelColor=%23d81b60\u0026amp;color=%23333\"\u003e \u003c/a\u003e\u003ca href=\"https://bsky.app/profile/tinybase.bsky.social\"\u003e\u003cimg src=\"https://img.shields.io/badge/Bluesky-Follow-blue?style=for-the-badge\u0026amp;logo=bluesky\u0026amp;logoColor=%23fff\u0026amp;color=%23333\u0026amp;labelColor=%230285FF\"\u003e \u003c/a\u003e\u003ca href=\"https://x.com/tinybasejs\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/badge/%2F%20Twitter-Follow-blue?style=for-the-badge\u0026amp;logo=x\u0026amp;logoColor=%23fff\u0026amp;color=%23333\u0026amp;labelColor=%23000\"\u003e \u003c/a\u003e\u003ca href=\"https://discord.com/invite/mGz3mevwP8\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/discord/1027918215323590676?style=for-the-badge\u0026amp;logo=discord\u0026amp;logoColor=%23fff\u0026amp;label=Discord\u0026amp;labelColor=%233131e8\u0026amp;color=%23333\"\u003e\u003c/a\u003e\u003cbr\u003e\u003ca href=\"https://github.com/tinyplex/tinybase/discussions\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge\u0026amp;logo=GitHub\u0026amp;logoColor=%23fff\u0026amp;label=Ideas\u0026amp;labelColor=%23d81b60\u0026amp;color=%23333\"\u003e \u003c/a\u003e\u003ca href=\"https://github.com/tinyplex/tinybase/issues\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge\u0026amp;logo=GitHub\u0026amp;logoColor=%23fff\u0026amp;label=Issues\u0026amp;labelColor=%23d81b60\u0026amp;color=%23333\"\u003e \u003c/a\u003e\u003ca href=\"#well-tested-and-documented\"\u003e\u003cimg src=\"https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge\u0026amp;logo=Vitest\u0026amp;logoColor=%23fff\u0026amp;color=%23333\u0026amp;labelColor=%2387c305\"\u003e \u003c/a\u003e\u003ca href=\"https://www.npmjs.com/package/tinybase/v/7.3.3\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/tinybase?style=for-the-badge\u0026amp;logo=npm\u0026amp;logoColor=%23fff\u0026amp;labelColor=%23bd0005\u0026amp;color=%23333\"\u003e\u003c/a\u003e\u003c/section\u003e\u003chr\u003e\u003csection\u003e\u003ch2 id=\"start-with-a-simple-key-value-store\"\u003eStart with a simple key-value store.\u003c/h2\u003e\u003cp\u003eCreating a \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e requires just a simple call to the \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/createstore/\"\u003e\u003ccode\u003ecreateStore\u003c/code\u003e\u003c/a\u003e function. Once you have one, you can easily set \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/values/\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e in it by unique \u003ca href=\"https://tinybase.org/api/common/type-aliases/identity/id/\"\u003e\u003ccode\u003eId\u003c/code\u003e\u003c/a\u003e. And of course you can easily get them back out again.\u003c/p\u003e\u003cp\u003eRead more about using keyed value data in \u003ca href=\"https://tinybase.org/guides/the-basics/\"\u003eThe Basics\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {createStore} from 'tinybase';\n\nconst store = createStore()\n  .setValues({employees: 3})\n  .setValue('open', true);\n\nconsole.log(store.getValues());\n// -\u003e {employees: 3, open: true}\n```\n\n\u003csection\u003e\u003ch2 id=\"level-up-to-use-tabular-data\"\u003eLevel up to use tabular data.\u003c/h2\u003e\u003cp\u003eFor other types of data applications, a tabular data structure is more useful. TinyBase lets you set and get nested \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/table/\"\u003e\u003ccode\u003eTable\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/row/\"\u003e\u003ccode\u003eRow\u003c/code\u003e\u003c/a\u003e, or \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e data, by unique \u003ca href=\"https://tinybase.org/api/common/type-aliases/identity/id/\"\u003e\u003ccode\u003eId\u003c/code\u003e\u003c/a\u003e - and in the same \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e as the keyed values!\u003c/p\u003e\u003cp\u003eRead more about setting and changing data in \u003ca href=\"https://tinybase.org/guides/the-basics/\"\u003eThe Basics\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nstore\n  .setTable('pets', {fido: {species: 'dog'}})\n  .setCell('pets', 'fido', 'color', 'brown');\n\nconsole.log(store.getRow('pets', 'fido'));\n// -\u003e {species: 'dog', color: 'brown'}\n```\n\n\u003csection\u003e\u003ch2 id=\"register-granular-listeners\"\u003eRegister granular listeners.\u003c/h2\u003e\u003cp\u003eThe magic starts to happen when you register listeners on a \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/value/\"\u003e\u003ccode\u003eValue\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/table/\"\u003e\u003ccode\u003eTable\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/row/\"\u003e\u003ccode\u003eRow\u003c/code\u003e\u003c/a\u003e, or \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e. They get called when any part of that object changes. You can also use wildcards - useful when you don\u0026#x27;t know the \u003ca href=\"https://tinybase.org/api/common/type-aliases/identity/id/\"\u003e\u003ccode\u003eId\u003c/code\u003e\u003c/a\u003e of the objects that might change.\u003c/p\u003e\u003cp\u003eRead more about listeners in the \u003ca href=\"https://tinybase.org/guides/the-basics/listening-to-stores/\"\u003eListening To Stores\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nconst listenerId = store.addTableListener('pets', () =\u003e\n  console.log('changed'),\n);\n\nstore.setCell('pets', 'fido', 'sold', false);\n// -\u003e 'changed'\n\nstore.delListener(listenerId);\n```\n\n\u003csection\u003e\u003ch2 id=\"call-hooks-to-bind-to-data\"\u003eCall hooks to bind to data.\u003c/h2\u003e\u003cp\u003eIf you\u0026#x27;re using React in your application, the optional \u003ca href=\"https://tinybase.org/api/ui-react/\"\u003e\u003ccode\u003eui-react\u003c/code\u003e\u003c/a\u003e module provides hooks to bind to the data in a \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\u003cp\u003eMore magic! The \u003ca href=\"https://tinybase.org/api/the-essentials/using-react/usecell/\"\u003e\u003ccode\u003euseCell\u003c/code\u003e\u003c/a\u003e hook in this example fetches the dog\u0026#x27;s color. But it also registers a listener on that cell that will fire and re-render the component whenever the value changes.\u003c/p\u003e\u003cp\u003eBasically you simply describe what data you want in your user interface and TinyBase will take care of the whole lifecycle of updating it for you.\u003c/p\u003e\u003cp\u003eRead more about the using hooks in the \u003ca href=\"https://tinybase.org/guides/building-uis/using-react-hooks/\"\u003eUsing React Hooks\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```jsx\nimport React from 'react';\nimport {createRoot} from 'react-dom/client';\nimport {useCell} from 'tinybase/ui-react';\n\nconst App1 = () =\u003e {\n  const color = useCell('pets', 'fido', 'color', store);\n  return \u003c\u003eColor: {color}\u003c/\u003e;\n};\n\nconst app = document.createElement('div');\nconst root = createRoot(app);\nroot.render(\u003cApp1 /\u003e);\nconsole.log(app.innerHTML);\n// -\u003e 'Color: brown'\n\nstore.setCell('pets', 'fido', 'color', 'walnut');\nconsole.log(app.innerHTML);\n// -\u003e 'Color: walnut'\n\nroot.unmount();\n```\n\n\u003csection\u003e\u003ch2 id=\"pre-built-reactive-components\"\u003ePre-built reactive components.\u003c/h2\u003e\u003cp\u003eThe \u003ca href=\"https://tinybase.org/api/ui-react/\"\u003e\u003ccode\u003eui-react\u003c/code\u003e\u003c/a\u003e module provides bare React components that let you build up a fully reactive user interface based on a \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\u003cp\u003eFor web applications in particular, the new \u003ca href=\"https://tinybase.org/api/ui-react-dom/\"\u003e\u003ccode\u003eui-react-dom\u003c/code\u003e\u003c/a\u003e module provides pre-built components for tabular display of your data, with lots of customization and interactivity options.\u003c/p\u003e\u003cp\u003eTry them out in the \u003ca href=\"https://tinybase.org/demos/ui-components/\"\u003eUI Components\u003c/a\u003e demos, and read more about the underlying \u003ca href=\"https://tinybase.org/api/ui-react/\"\u003e\u003ccode\u003eui-react\u003c/code\u003e\u003c/a\u003e module in the \u003ca href=\"https://tinybase.org/guides/building-uis/\"\u003eBuilding UIs\u003c/a\u003e guides.\u003c/p\u003e\u003c/section\u003e\u003cimg src=\"https://tinybase.org/ui-react-dom.webp\"\u003e\u003csection\u003e\u003ch2 id=\"an-inspector-for-your-data\"\u003eAn inspector for your data.\u003c/h2\u003e\u003cp\u003eIf you are building a web application, the new \u003ca href=\"https://tinybase.org/api/the-essentials/using-react/inspector/\"\u003e\u003ccode\u003eInspector\u003c/code\u003e\u003c/a\u003e component lets you overlay a view of the data in your \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"https://tinybase.org/api/indexes/interfaces/indexes/indexes/\"\u003e\u003ccode\u003eIndexes\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"https://tinybase.org/api/relationships/interfaces/relationships/relationships/\"\u003e\u003ccode\u003eRelationships\u003c/code\u003e\u003c/a\u003e, and so on. You can even edit the data in place and see it update in your app immediately.\u003c/p\u003e\u003cp\u003eRead more about this powerful new tool in the \u003ca href=\"https://tinybase.org/guides/inspecting-data/\"\u003eInspecting Data\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\u003cimg src=\"https://tinybase.org/inspector.webp\"\u003e\u003csection\u003e\u003ch2 id=\"apply-schemas-to-tables-values\"\u003eApply schemas to tables \u0026amp; values.\u003c/h2\u003e\u003cp\u003eWant clean data? You can add a \u003ca href=\"https://tinybase.org/api/store/type-aliases/schema/valuesschema/\"\u003e\u003ccode\u003eValuesSchema\u003c/code\u003e\u003c/a\u003e or a \u003ca href=\"https://tinybase.org/api/store/type-aliases/schema/tablesschema/\"\u003e\u003ccode\u003eTablesSchema\u003c/code\u003e\u003c/a\u003e to a \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e to ensure that they are always what you expect by constraining types, and providing defaults. There are even TypeScript definitions that infer API types from the data schemas you apply.\u003c/p\u003e\u003cp\u003eAnd our \u0026#x27;schematizer\u0026#x27; modules let you convert schemas from libraries like Zod, TypeBox, Valibot, ArkType, Yup, and Effect Schema into TinyBase at runtime.\u003c/p\u003e\u003cp\u003eRead more about schemas in the \u003ca href=\"https://tinybase.org/guides/schemas/\"\u003eSchemas\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nstore.setTablesSchema({\n  pets: {\n    species: {type: 'string'},\n    color: {type: 'string'},\n    sold: {type: 'boolean', default: false},\n  },\n});\n\nstore.setRow('pets', 'polly', {species: 'parrot'});\nconsole.log(store.getRow('pets', 'polly'));\n// -\u003e {species: 'parrot', sold: false}\n\nstore.delTablesSchema();\n```\n\n\u003csection\u003e\u003ch2 id=\"synchronize-between-devices\"\u003eSynchronize between devices.\u003c/h2\u003e\u003cp\u003eThe \u003ca href=\"https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/\"\u003e\u003ccode\u003eMergeableStore\u003c/code\u003e\u003c/a\u003e type acts as a native CRDT, letting you merge data and synchronize it between clients and systems - or even a server. The synchronization protocol can run over WebSockets, the browser BroadcastChannel, or your own custom synchronization medium.\u003c/p\u003e\u003cp\u003eRead more about these techniques in the \u003ca href=\"https://tinybase.org/guides/synchronization/\"\u003eSynchronization\u003c/a\u003e guides.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {WebSocketServer, WebSocket} from 'ws';\nimport {createMergeableStore} from 'tinybase';\nimport {createWsServer} from 'tinybase/synchronizers/synchronizer-ws-server';\nimport {createWsSynchronizer} from 'tinybase/synchronizers/synchronizer-ws-client';\n\n// On a server machine:\nconst server = createWsServer(\n  new WebSocketServer({port: 8040}),\n);\n\n// On a client machine:\nconst store1 = createMergeableStore();\nconst synchronizer1 = await createWsSynchronizer(\n  store1,\n  new WebSocket('ws://localhost:8040'),\n);\nawait synchronizer1.startSync();\n\n// ...\n\nawait synchronizer1.destroy();\nawait server.destroy();\n```\n\n\u003csection\u003e\u003ch2 id=\"persist-to-storage-databases-more\"\u003ePersist to storage, databases, \u0026amp; more.\u003c/h2\u003e\u003cp\u003eYou can easily persist a \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e between browser page reloads or sessions. You can also synchronize it with a web endpoint, or (if you\u0026#x27;re using TinyBase in an appropriate environment), load and save it to a file. You can bind TinyBase to various flavors of \u003ca href=\"https://tinybase.org/guides/schemas-and-persistence/database-persistence/\"\u003edatabase\u003c/a\u003e, or to \u003ca href=\"https://yjs.dev/\"\u003eYjs\u003c/a\u003e and \u003ca href=\"https://automerge.org/\"\u003eAutomerge\u003c/a\u003e CRDT documents.\u003c/p\u003e\u003cp\u003eRead more about persisters in the \u003ca href=\"https://tinybase.org/guides/persistence/\"\u003ePersistence\u003c/a\u003e guides.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {createSessionPersister} from 'tinybase/persisters/persister-browser';\n\nconst persister = createSessionPersister(store, 'demo');\nawait persister.save();\n\nconsole.log(sessionStorage.getItem('demo'));\n// -\u003e\n`\n[\n  {\n    \"pets\":{\n      \"fido\":{\"species\":\"dog\",\"color\":\"walnut\",\"sold\":false},\n      \"polly\":{\"species\":\"parrot\",\"sold\":false}\n    }\n  },\n  {\"employees\":3,\"open\":true}\n]\n`;\n\nawait persister.destroy();\nawait sessionStorage.clear();\n```\n\n\u003csection\u003e\u003ch2 id=\"build-complex-queries-with-tinyql\"\u003eBuild complex queries with \u003ca href=\"https://tinybase.org/guides/using-queries/tinyql/\"\u003eTinyQL\u003c/a\u003e.\u003c/h2\u003e\u003cp\u003eThe \u003ca href=\"https://tinybase.org/api/queries/interfaces/queries/queries/\"\u003e\u003ccode\u003eQueries\u003c/code\u003e\u003c/a\u003e object lets you query data across tables, with filtering and aggregation - using a SQL-adjacent syntax called \u003ca href=\"https://tinybase.org/guides/using-queries/tinyql/\"\u003eTinyQL\u003c/a\u003e.\u003c/p\u003e\u003cp\u003eAccessors and listeners let you sort and paginate the results efficiently, making building rich tabular interfaces easier than ever.\u003c/p\u003e\u003cp\u003eIn this example, we have two tables: of pets and their owners. They are joined together by the pet\u0026#x27;s ownerId \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e. We select the pet\u0026#x27;s species, and the owner\u0026#x27;s state, and then aggregate the prices for the combinations.\u003c/p\u003e\u003cp\u003eWe access the results by descending price, essentially answering the question: \u0026quot;which is the highest-priced species, and in which state?\u0026quot;\u003c/p\u003e\u003cp\u003eNeedless to say, the results are reactive too! You can add listeners to queries, and since v7.2, even parameterize them.\u003c/p\u003e\u003cp\u003eRead more about \u003ca href=\"https://tinybase.org/api/queries/interfaces/queries/queries/\"\u003e\u003ccode\u003eQueries\u003c/code\u003e\u003c/a\u003e in the \u003ca href=\"https://tinybase.org/guides/releases/#v2-0\"\u003ev2.0 Release Notes\u003c/a\u003e, the \u003ca href=\"https://tinybase.org/guides/using-queries/\"\u003eUsing Queries\u003c/a\u003e guide, and the \u003ca href=\"https://tinybase.org/demos/car-analysis/\"\u003eCar Analysis\u003c/a\u003e demo and \u003ca href=\"https://tinybase.org/demos/movie-database/\"\u003eMovie Database\u003c/a\u003e demo.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {createQueries} from 'tinybase';\n\nstore\n  .setTable('pets', {\n    fido: {species: 'dog', ownerId: '1', price: 5},\n    rex: {species: 'dog', ownerId: '2', price: 4},\n    felix: {species: 'cat', ownerId: '2', price: 3},\n    cujo: {species: 'dog', ownerId: '3', price: 4},\n  })\n  .setTable('owners', {\n    1: {name: 'Alice', state: 'CA'},\n    2: {name: 'Bob', state: 'CA'},\n    3: {name: 'Carol', state: 'WA'},\n  });\n\nconst queries = createQueries(store);\nqueries.setQueryDefinition(\n  'prices',\n  'pets',\n  ({select, join, group}) =\u003e {\n    select('species');\n    select('owners', 'state');\n    select('price');\n    join('owners', 'ownerId');\n    group('price', 'avg').as('avgPrice');\n  },\n);\n\nqueries\n  .getResultSortedRowIds('prices', 'avgPrice', true)\n  .forEach((rowId) =\u003e {\n    console.log(queries.getResultRow('prices', rowId));\n  });\n// -\u003e {species: 'dog', state: 'CA', avgPrice: 4.5}\n// -\u003e {species: 'dog', state: 'WA', avgPrice: 4}\n// -\u003e {species: 'cat', state: 'CA', avgPrice: 3}\n\nqueries.destroy();\n```\n\n\u003csection\u003e\u003ch2 id=\"define-metrics-and-aggregations\"\u003eDefine metrics and aggregations.\u003c/h2\u003e\u003cp\u003eA \u003ca href=\"https://tinybase.org/api/metrics/interfaces/metrics/metrics/\"\u003e\u003ccode\u003eMetrics\u003c/code\u003e\u003c/a\u003e object makes it easy to keep a running aggregation of \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e values in each \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/row/\"\u003e\u003ccode\u003eRow\u003c/code\u003e\u003c/a\u003e of a \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/table/\"\u003e\u003ccode\u003eTable\u003c/code\u003e\u003c/a\u003e. This is useful for counting rows, but also supports averages, ranges of values, or arbitrary aggregations.\u003c/p\u003e\u003cp\u003eIn this example, we create a new table of the pet species, and keep a track of which is most expensive. When we add horses to our pet store, the listener detects that the highest price has changed.\u003c/p\u003e\u003cp\u003eRead more about \u003ca href=\"https://tinybase.org/api/metrics/interfaces/metrics/metrics/\"\u003e\u003ccode\u003eMetrics\u003c/code\u003e\u003c/a\u003e in the \u003ca href=\"https://tinybase.org/guides/using-metrics/\"\u003eUsing Metrics\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {createMetrics} from 'tinybase';\n\nstore.setTable('species', {\n  dog: {price: 5},\n  cat: {price: 4},\n  worm: {price: 1},\n});\n\nconst metrics = createMetrics(store);\nmetrics.setMetricDefinition(\n  'highestPrice', // metricId\n  'species', //      tableId to aggregate\n  'max', //          aggregation\n  'price', //        cellId to aggregate\n);\n\nconsole.log(metrics.getMetric('highestPrice'));\n// -\u003e 5\n\nmetrics.addMetricListener('highestPrice', () =\u003e\n  console.log(metrics.getMetric('highestPrice')),\n);\nstore.setCell('species', 'horse', 'price', 20);\n// -\u003e 20\n\nmetrics.destroy();\n```\n\n\u003csection\u003e\u003ch2 id=\"create-indexes-for-fast-lookups\"\u003eCreate indexes for fast lookups.\u003c/h2\u003e\u003cp\u003eAn \u003ca href=\"https://tinybase.org/api/indexes/interfaces/indexes/indexes/\"\u003e\u003ccode\u003eIndexes\u003c/code\u003e\u003c/a\u003e object makes it easy to look up all the \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/row/\"\u003e\u003ccode\u003eRow\u003c/code\u003e\u003c/a\u003e objects that have a certain value in a \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\u003cp\u003eIn this example, we create an index on the \u003ccode\u003especies\u003c/code\u003e \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e values. We can then get the the list of distinct \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e value present for that index (known as \u0026#x27;slices\u0026#x27;), and the set of \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/row/\"\u003e\u003ccode\u003eRow\u003c/code\u003e\u003c/a\u003e objects that match each value.\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://tinybase.org/api/indexes/interfaces/indexes/indexes/\"\u003e\u003ccode\u003eIndexes\u003c/code\u003e\u003c/a\u003e objects are reactive too. So you can set listeners on them just as you do for the data in the underlying \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\u003cp\u003eRead more about \u003ca href=\"https://tinybase.org/api/indexes/interfaces/indexes/indexes/\"\u003e\u003ccode\u003eIndexes\u003c/code\u003e\u003c/a\u003e in the \u003ca href=\"https://tinybase.org/guides/using-indexes/\"\u003eUsing Indexes\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {createIndexes} from 'tinybase';\n\nconst indexes = createIndexes(store);\nindexes.setIndexDefinition(\n  'bySpecies', // indexId\n  'pets', //      tableId to index\n  'species', //   cellId to index\n);\n\nconsole.log(indexes.getSliceIds('bySpecies'));\n// -\u003e ['dog', 'cat']\nconsole.log(indexes.getSliceRowIds('bySpecies', 'dog'));\n// -\u003e ['fido', 'rex', 'cujo']\n\nindexes.addSliceIdsListener('bySpecies', () =\u003e\n  console.log(indexes.getSliceIds('bySpecies')),\n);\nstore.setRow('pets', 'lowly', {species: 'worm'});\n// -\u003e ['dog', 'cat', 'worm']\n\nindexes.destroy();\n```\n\n\u003csection\u003e\u003ch2 id=\"model-table-relationships\"\u003eModel table relationships.\u003c/h2\u003e\u003cp\u003eA \u003ca href=\"https://tinybase.org/api/relationships/interfaces/relationships/relationships/\"\u003e\u003ccode\u003eRelationships\u003c/code\u003e\u003c/a\u003e object lets you associate a \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/row/\"\u003e\u003ccode\u003eRow\u003c/code\u003e\u003c/a\u003e in a local \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/table/\"\u003e\u003ccode\u003eTable\u003c/code\u003e\u003c/a\u003e with the \u003ca href=\"https://tinybase.org/api/common/type-aliases/identity/id/\"\u003e\u003ccode\u003eId\u003c/code\u003e\u003c/a\u003e of a \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/row/\"\u003e\u003ccode\u003eRow\u003c/code\u003e\u003c/a\u003e in a remote \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/table/\"\u003e\u003ccode\u003eTable\u003c/code\u003e\u003c/a\u003e. You can also reference a table to itself to create linked lists.\u003c/p\u003e\u003cp\u003eIn this example, the \u003ccode\u003especies\u003c/code\u003e \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/cell/\"\u003e\u003ccode\u003eCell\u003c/code\u003e\u003c/a\u003e of the \u003ccode\u003epets\u003c/code\u003e \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/table/\"\u003e\u003ccode\u003eTable\u003c/code\u003e\u003c/a\u003e is used to create a relationship to the \u003ccode\u003especies\u003c/code\u003e \u003ca href=\"https://tinybase.org/api/store/type-aliases/store/table/\"\u003e\u003ccode\u003eTable\u003c/code\u003e\u003c/a\u003e, so that we can access the price of a given pet.\u003c/p\u003e\u003cp\u003eLike everything else, you can set listeners on \u003ca href=\"https://tinybase.org/api/relationships/interfaces/relationships/relationships/\"\u003e\u003ccode\u003eRelationships\u003c/code\u003e\u003c/a\u003e too.\u003c/p\u003e\u003cp\u003eRead more about \u003ca href=\"https://tinybase.org/api/relationships/interfaces/relationships/relationships/\"\u003e\u003ccode\u003eRelationships\u003c/code\u003e\u003c/a\u003e in the \u003ca href=\"https://tinybase.org/guides/using-relationships/\"\u003eUsing Relationships\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {createRelationships} from 'tinybase';\n\nconst relationships = createRelationships(store);\nrelationships.setRelationshipDefinition(\n  'petSpecies', // relationshipId\n  'pets', //       local tableId to link from\n  'species', //    remote tableId to link to\n  'species', //    cellId containing remote key\n);\n\nconsole.log(\n  store.getCell(\n    relationships.getRemoteTableId('petSpecies'),\n    relationships.getRemoteRowId('petSpecies', 'fido'),\n    'price',\n  ),\n);\n// -\u003e 5\n\nrelationships.destroy();\n```\n\n\u003csection\u003e\u003ch2 id=\"set-checkpoints-for-an-undo-stack\"\u003eSet checkpoints for an undo stack.\u003c/h2\u003e\u003cp\u003eA \u003ca href=\"https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/\"\u003e\u003ccode\u003eCheckpoints\u003c/code\u003e\u003c/a\u003e object lets you set checkpoints on a \u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003e\u003ccode\u003eStore\u003c/code\u003e\u003c/a\u003e. Move forward and backward through them to create undo and redo functions.\u003c/p\u003e\u003cp\u003eIn this example, we set a checkpoint, then sell one of the pets. Later, the pet is brought back to the shop, and we go back to that checkpoint to revert the store to its previous state.\u003c/p\u003e\u003cp\u003eRead more about \u003ca href=\"https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/\"\u003e\u003ccode\u003eCheckpoints\u003c/code\u003e\u003c/a\u003e in the \u003ca href=\"https://tinybase.org/guides/using-checkpoints/\"\u003eUsing Checkpoints\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\n\n```js\nimport {createCheckpoints} from 'tinybase';\n\nconst checkpoints = createCheckpoints(store);\n\nstore.setCell('pets', 'felix', 'sold', false);\ncheckpoints.addCheckpoint('pre-sale');\n\nstore.setCell('pets', 'felix', 'sold', true);\nconsole.log(store.getCell('pets', 'felix', 'sold'));\n// -\u003e true\n\ncheckpoints.goBackward();\nconsole.log(store.getCell('pets', 'felix', 'sold'));\n// -\u003e false\n```\n\n\u003csection\u003e\u003ch2 id=\"did-we-say-tiny\"\u003eDid we say tiny?\u003c/h2\u003e\u003cp\u003eIf you use the basic \u003ca href=\"https://tinybase.org/api/store/\"\u003e\u003ccode\u003estore\u003c/code\u003e\u003c/a\u003e module alone, you\u0026#x27;ll only add a gzipped \u003cem\u003e5.4kB\u003c/em\u003e to your app. Incrementally add the other modules as you need more functionality, or get it all for \u003cem\u003e12.1kB\u003c/em\u003e.\u003c/p\u003e\u003cp\u003eThe optional \u003ca href=\"https://tinybase.org/api/ui-react/\"\u003e\u003ccode\u003eui-react\u003c/code\u003e\u003c/a\u003e module is just \u003cem\u003e5.5kB\u003c/em\u003e, the ui-react-dom components are another \u003cem\u003e3.8kB\u003c/em\u003e, and everything is super fast. Life is easy when you have zero dependencies!\u003c/p\u003e\u003cp\u003eRead more about how TinyBase is structured and packaged in the \u003ca href=\"https://tinybase.org/guides/how-tinybase-is-built/architecture/\"\u003eArchitecture\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\u003cdiv class=\"table\"\u003e\u003ctable class=\"fixed\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003cth\u003e \u003c/th\u003e\u003cth\u003eMinified .js.gz\u003c/th\u003e\u003cth\u003eSource .js\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003e\u003ca href=\"https://tinybase.org/api/store/\"\u003etinybase/store\u003c/a\u003e (minimal)\u003c/th\u003e\u003ctd\u003e5.4kB\u003c/td\u003e\u003ctd\u003e54.6kB\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003etinybase (complete)\u003c/th\u003e\u003ctd\u003e12.1kB\u003c/td\u003e\u003ctd\u003e127.0kB\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003e\u003ca href=\"https://tinybase.org/api/ui-react/\"\u003eui-react\u003c/a\u003e\u003c/th\u003e\u003ctd\u003e5.5kB\u003c/td\u003e\u003ctd\u003e59.8kB\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003e\u003ca href=\"https://tinybase.org/api/ui-react-dom/\"\u003eui-react-dom\u003c/a\u003e\u003c/th\u003e\u003ctd\u003e3.8kB\u003c/td\u003e\u003ctd\u003e34.0kB\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003csection\u003e\u003ch2 id=\"well-tested-and-documented\"\u003eWell tested and documented.\u003c/h2\u003e\u003cp\u003eTinyBase has \u003cem\u003e100.0%\u003c/em\u003e test coverage, including the code throughout the documentation - even on this page! The guides, demos, and API examples are designed to make it as easy as possible for you to get your TinyBase-powered app up and running.\u003c/p\u003e\u003cp\u003eRead more about how TinyBase is tested in the Unit \u003ca href=\"https://tinybase.org/guides/how-tinybase-is-built/testing/\"\u003eTesting\u003c/a\u003e guide.\u003c/p\u003e\u003c/section\u003e\u003cdiv class=\"table\"\u003e\u003ctable class=\"fixed\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003cth width=\"30%\"\u003e \u003c/th\u003e\u003cth\u003eTotal\u003c/th\u003e\u003cth\u003eTested\u003c/th\u003e\u003cth\u003eCoverage\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003eLines\u003c/th\u003e\u003ctd\u003e2,408\u003c/td\u003e\u003ctd\u003e2,408\u003c/td\u003e\u003ctd\u003e100.0%\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003eStatements\u003c/th\u003e\u003ctd\u003e2,617\u003c/td\u003e\u003ctd\u003e2,617\u003c/td\u003e\u003ctd\u003e100.0%\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003eFunctions\u003c/th\u003e\u003ctd\u003e1,046\u003c/td\u003e\u003ctd\u003e1,046\u003c/td\u003e\u003ctd\u003e100.0%\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003eBranches\u003c/th\u003e\u003ctd\u003e906\u003c/td\u003e\u003ctd\u003e906\u003c/td\u003e\u003ctd\u003e100.0%\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003eTests\u003c/th\u003e\u003ctd colspan=\"3\"\u003e7,291\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth class=\"right\"\u003eAssertions\u003c/th\u003e\u003ctd colspan=\"3\"\u003e32,336\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003chr\u003e\u003csection id=\"sponsors\"\u003e\u003ch2 id=\"proud-to-be-supported-by\"\u003eProud to be supported by:\u003c/h2\u003e\u003ca href=\"https://github.com/fastrepl\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/fastrepl.png?size=48\" title=\"fastrepl\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/expo\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/expo.png?size=48\" title=\"expo\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/dylmye\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/dylmye.png?size=48\" title=\"dylmye\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/ComputelessComputer\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/ComputelessComputer.png?size=48\" title=\"ComputelessComputer\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/cancelself\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/cancelself.png?size=48\" title=\"cancelself\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/cpojer\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/cpojer.png?size=48\" title=\"cpojer\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/beekeeb\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/beekeeb.png?size=48\" title=\"beekeeb\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/WonderPanda\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/WonderPanda.png?size=48\" title=\"WonderPanda\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/arpitBhalla\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/arpitBhalla.png?size=48\" title=\"arpitBhalla\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003c/section\u003e\u003csection id=\"users\"\u003e\u003ch2 id=\"excited-to-be-used-by\"\u003eExcited to be used by:\u003c/h2\u003e\u003ca href=\"https://github.com/behrends\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/behrends.png?size=48\" title=\"behrends\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/betomoedano\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/betomoedano.png?size=48\" title=\"betomoedano\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/brentvatne\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/brentvatne.png?size=48\" title=\"brentvatne\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/byCedric\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/byCedric.png?size=48\" title=\"byCedric\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/circadian-risk\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/circadian-risk.png?size=48\" title=\"circadian-risk\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/cpojer\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/cpojer.png?size=48\" title=\"cpojer\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/cubecull\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/cubecull.png?size=48\" title=\"cubecull\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/erwinkn\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/erwinkn.png?size=48\" title=\"erwinkn\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/expo\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/expo.png?size=48\" title=\"expo\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/ezra-en\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/ezra-en.png?size=48\" title=\"ezra-en\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/feychenie\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/feychenie.png?size=48\" title=\"feychenie\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/flaming-codes\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/flaming-codes.png?size=48\" title=\"flaming-codes\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/fostertheweb\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/fostertheweb.png?size=48\" title=\"fostertheweb\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/Giulio987\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/Giulio987.png?size=48\" title=\"Giulio987\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/hi-ogawa\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/hi-ogawa.png?size=48\" title=\"hi-ogawa\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/itsdevcoffee\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/itsdevcoffee.png?size=48\" title=\"itsdevcoffee\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/jbolda\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/jbolda.png?size=48\" title=\"jbolda\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/Kayoo-asso\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/Kayoo-asso.png?size=48\" title=\"Kayoo-asso\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/kotofurumiya\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/kotofurumiya.png?size=48\" title=\"kotofurumiya\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/Kudo\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/Kudo.png?size=48\" title=\"Kudo\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/learn-anything\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/learn-anything.png?size=48\" title=\"learn-anything\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/lluc\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/lluc.png?size=48\" title=\"lluc\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/marksteve\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/marksteve.png?size=48\" title=\"marksteve\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/miking-the-viking\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/miking-the-viking.png?size=48\" title=\"miking-the-viking\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/mjamesderocher\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/mjamesderocher.png?size=48\" title=\"mjamesderocher\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/mouktardev\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/mouktardev.png?size=48\" title=\"mouktardev\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/nickmessing\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/nickmessing.png?size=48\" title=\"nickmessing\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/nikitavoloboev\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/nikitavoloboev.png?size=48\" title=\"nikitavoloboev\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/nkzw-tech\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/nkzw-tech.png?size=48\" title=\"nkzw-tech\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/palerdot\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/palerdot.png?size=48\" title=\"palerdot\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/PorcoRosso85\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/PorcoRosso85.png?size=48\" title=\"PorcoRosso85\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/primodiumxyz\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/primodiumxyz.png?size=48\" title=\"primodiumxyz\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/shaneosullivan\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/shaneosullivan.png?size=48\" title=\"shaneosullivan\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/sudo-self\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/sudo-self.png?size=48\" title=\"sudo-self\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/SuperSonicHub1\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/SuperSonicHub1.png?size=48\" title=\"SuperSonicHub1\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/threepointone\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/threepointone.png?size=48\" title=\"threepointone\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/uptonking\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/uptonking.png?size=48\" title=\"uptonking\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/ViktorZhurbin\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/ViktorZhurbin.png?size=48\" title=\"ViktorZhurbin\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/wilkerlucio\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/wilkerlucio.png?size=48\" title=\"wilkerlucio\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003ca href=\"https://github.com/WonderPanda\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/WonderPanda.png?size=48\" title=\"WonderPanda\" width=\"48\" height=\"48\"\u003e\u003c/a\u003e\u003c/section\u003e\u003chr\u003e\u003cp\u003e\u003ca class=\"start\" href=\"https://tinybase.org/guides/the-basics/getting-started/\"\u003eGet started\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://tinybase.org/demos/\"\u003eTry the demos\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://tinybase.org/api/the-essentials/creating-stores/store/\"\u003eRead the docs\u003c/a\u003e\u003c/p\u003e\u003chr\u003e\u003csection id=\"family\"\u003e\u003ch2 id=\"meet-the-family\"\u003eMeet the family\u003c/h2\u003e\u003cp\u003eTinyBase is part of a group of small libraries designed to help make rich client and local-first apps easier to build. Check out the others!\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://synclets.org\" target=\"_blank\"\u003e\u003cimg src=\"https://synclets.org/favicon.svg?asImg\" width=\"48\"\u003e\u003cbr\u003e\u003cb\u003eSynclets\u003c/b\u003e\u003c/a\u003e\u003cbr\u003eAn open, storage-agnostic, sync engine development kit.\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://tinywidgets.org\" target=\"_blank\"\u003e\u003cimg src=\"https://tinywidgets.org/favicon.svg?asImg\" width=\"48\"\u003e\u003cbr\u003e\u003cb\u003eTinyWidgets\u003c/b\u003e\u003c/a\u003e\u003cbr\u003eA collection of tiny, reusable, UI components.\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://tinytick.org\" target=\"_blank\"\u003e\u003cimg src=\"https://tinytick.org/favicon.svg?asImg\" width=\"48\"\u003e\u003cbr\u003e\u003cb\u003eTinyTick\u003c/b\u003e\u003c/a\u003e\u003cbr\u003eA tiny but very useful task orchestrator.\u003c/p\u003e\u003c/section\u003e\u003chr\u003e\u003csection id=\"about\"\u003e\u003ch2 id=\"about\"\u003eAbout\u003c/h2\u003e\u003cp\u003eModern apps deserve better. Why trade reactive user experiences to be able to use relational data? Or sacrifice features for bundle size? And why does the cloud do all the work \u003ca href=\"https://localfirstweb.dev/\" target=\"_blank\"\u003eanyway\u003c/a\u003e?\u003c/p\u003e\u003cp\u003eBuilding TinyBase was originally an interesting exercise for \u003ca rel=\"me\" href=\"https://tripleodeon.com\"\u003eme\u003c/a\u003e in API design, minification, and documentation. But now it has taken on a life of its own, and has grown beyond my wildest expectations.\u003c/p\u003e\u003cp\u003eIt could not have been built without these great \u003ca href=\"https://tinybase.org/guides/how-tinybase-is-built/credits/#giants\"\u003eprojects\u003c/a\u003e and \u003ca href=\"https://tinybase.org/guides/how-tinybase-is-built/credits/#and-friends\"\u003efriends\u003c/a\u003e, and I hope you enjoy using it as much as I do building it!\u003c/p\u003e\u003c/section\u003e\u003csection id=\"story\"\u003e\u003ch2 id=\"the-story\"\u003eThe story\u003c/h2\u003e\u003ca href=\"https://youtu.be/hXL7OkW-Prk?t=1232\" target=\"_blank\"\u003e\u003cimg src=\"https://tinybase.org/youtube.webp\"\u003e\u003c/a\u003e\u003c/section\u003e","funding_links":["https://github.com/sponsors/jamesgpearce"],"categories":["TypeScript","By Industry","typescript"],"sub_categories":["Web Development"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinyplex%2Ftinybase","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftinyplex%2Ftinybase","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftinyplex%2Ftinybase/lists"}