Skip to content
Agentmart
Submit a tool

sync-data-firebase

Sync app data to Firebase — Firestore documents, cross-device sync, server-authoritative state (credit balances, settings, user profiles, saved items).

Skill by KotlinFoundation

IndexedMIT★ 28
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/kotlinfoundation-sync-data-firebase

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Sync app data to Firebase — Firestore documents, cross-device sync, server-authoritative state (credit balances, settings, user profiles, saved items). Use when the developer wants to store data in Firestore, sync data across devices, back up local data to the cloud, make a balance or entitlement server-verified, or asks "how do I sync X with Firebase". Starts with a required question about the wasmJs target, because no Firebase client SDK supports Kotlin/Wasm.

Use cases: backend, data

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/sync-data-firebase

What's inside

Skill name
sync-data-firebase
Description
Sync app data to Firebase — Firestore documents, cross-device sync, server-authoritative state (credit balances, settings, user profiles, saved items). Use when the developer wants to store data in Firestore, sync data across devices, back up local data to the cloud, make a balance or entitlement server-verified, or asks "how do I sync X with Firebase". Starts with a required question about the wasmJs target, because no Firebase client SDK supports Kotlin/Wasm.
License
MIT
Instructions
143 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Sync app data to Firebase

The kit stores data locally by default — Room for structured data, DataStore for preferences. This
skill covers moving some of it to Firebase so it survives reinstalls, follows the user across devices,
or becomes server-authoritative.

Firebase setup (project, config files, anonymous auth) must already be done — that's `setup-firebase`.

## 0. Ask the developer first — this step is not optional

> [!IMPORTANT]
> There is **no Firebase client SDK for the `wasmJs` target**. The GitLive
> [firebase-kotlin-sdk](https://github.com/GitLiveApp/firebase-kotlin-sdk) covers Android, iOS, JVM and
> JS but **not** Kotlin/Wasm, so a Firestore call in `commonMain` breaks the web build. Desktop is never
> the blocker — the browser target is.
>
> **Put the question to the developer and wait for their answer.** Do not choose for them, do not
> answer with a recommendation as if it were settled, and never drop a target silently. The web build
> is a deliverable they chose; trading it away is theirs to decide.

Present both options:

| | **Keep Wasm** (present first) | **Drop Wasm** |
|---|---|---|
| How | Firestore lives behind the Cloud Functions backend this kit already ships. Client speaks plain REST. | GitLive SDK in `commonMain`, client talks to Firestore directly. |
| Targets | All five keep working. | No browser build. Android, iOS, Desktop, JS only. |
| Cost | More backend code: functions, security rules, DTOs, an API service. | Shorter path. Realtime listeners and offline persistence come free. |
| Reversible | Yes. | Removing/re-adding the `wasmJs` target is a real chunk of work. |

The rest of this skill covers the **Keep Wasm** path. For Drop Wasm, check the [GitHub releases page](https://github.com/GitLiveApp/firebase-kotlin-sdk/releases) explicitly
to take the latest GitLive version — don't pin an old one — and remove the `wasmJs` target from `shared`, `designsystem`, and `webApp`. Use **at least `3.0.0-alpha01`** of the GitLive Firebase Kotlin SDK: KMPAuth 3.0.5 already depends on GitLive 3, so anything older clashes over `firebase-ios-sdk` on iOS.


## 1. Ask what the sync is actually for

The answer decides how much you build. These are different products:

- **Backup / restore.** Server mirrors local state so a reinstall recovers it. Client stays the
  authority. Cheapest — no rule logic moves server-side.
- **Cross-device continuity.** Same state on phone and tablet. **Anonymous auth gives a per-install
  uid**, so sync alone achieves nothing here — the user needs a real account first (`enable-auth`) and
  an anon→permanent account link. Say this out loud before building; it's the most common wrong
  assumption.
- **Server-authoritative / anti-cheat.** The server holds the value and validates every mutation. This
  is the expensive one: any business rules that currently run in Kotlin have to be ported to the
  functions or duplicated.
- **Server-verified purchases.** Entitlement or balance grants move off the client onto a store
  webhook. Usually the highest-value piece and independent of the other three.

## 2. Architecture (Wasm-safe)

```
KMP app (Android, iOS, Desktop, Wasm, JS)
   │  HTTPS + Firebase ID token
   ▼
HTTPS Cloud Functions  ──►  Firebase Admin SDK  ──►  Cloud Firestore
```

Rules:

- Every Firestore read/write goes through a Cloud Function. The client never touches Firestore.
- Functions use the Firebase Admin SDK (already a dependency in `Web/functions/package.json`), not the
  Firestore REST API.
- Functions verify the caller's ID token before any database operation —
  `Web/functions/utils/validation.js` → `admin.auth().verifyIdToken(...)` is the existing helper.
- Plain REST endpoints, so one client implementation serves every platform.
- Firestore security rules deny all direct client access. Admin SDK bypasses rules by design.

## 3. Backend — `Web/functions/`

Add handlers under `Web/functions/api/`, export them from `Web/functions/index.js`, deploy via
`integrate-web-proxy`. Store the state under the caller's uid, never a uid taken from the request body:

```
users/{uid}/<collection>/{docId}
```

**Idempotency.** Any mutation the client might retry (a spend, a grant, a purchase) needs a
client-generated id used as the document id, so a retry over a flaky connection is a no-op instead of a
double-apply. The client already generates `Uuid.random()` in several places — reuse that value rather
than inventing a server id.

## 4. Client — normal API service, no Firebase types

Firebase stays invisible to the app. Follow `add-api-service`:

1. DTOs in `data/source/remote/request/` + `response/` (`@Serializable`, `asDomain()` mappers).
2. An `*ApiService` under `data/source/remote/apiservices/`, returning raw response types.
3. The repository wraps in `Result` via `BackgroundExecutor` and does the mapping.

Requests go through the Firebase-interceptor Ktor client against
`AppConfiguration.CLOUD_FUNCTIONS_URL` — the same path the AI proxy uses, so the ID token is attached
for you. A blank `CLOUD_FUNCTIONS_URL` means no backend is deployed; the feature must degrade to
local-only rather than crash.

## 5. Keep the local store as the offline layer

Don't delete the Room/DataStore path when the server arrives. Local becomes the cache:

- Reads serve from local, then reconcile with the server response.
- Writes apply locally first, queue for the server, and carry the idempotency id.
- Add a `synced` flag to the affected entity, plus a Room `@Database(version = …)` bump and a
  `Migration` if the app has already shipped.
- Decide and write down the conflict policy — usually server wins, clamped so a value can't go
  negative.
- **Migrate existing installs once.** Users already have local state. Upload it on first sync, guarded
  by a one-shot preference flag, or they lose it on update.

## 6. Worked example — credit balance

Credits are the most common thing developers want synced, so the shape is spelled out here.

Today they're fully local: per-source counters and `KEY_CREDIT_GENERAL_BALANCE` in DataStore, plus a
Room ledger in `credit_transaction`. `CreditRepository` applies the `CreditSystemConfig` rules
(one-time bonuses, recurring refills, `condition` lambdas that read `SubscriptionRepository`).

- Keep `CreditRepository`'s public API unchanged — `balance`, `useCredits`, `addCredits`,
  `getRecentTransactionsFlow`. Inject the remote source behind it so screens and ViewModels don't move.
- Firestore: `users/{uid}/credit` holding `{balance, sources: {id: {remaining, nextResetAt, granted}},

From KotlinFoundation/kmp-contest-starter-kit, MIT.

More from KotlinFoundation/kmp-contest-starter-kit

Signals

Stars
28
Forks
13
Open issues
1
Last commit (this folder)
Aug 14, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from KotlinFoundation

Cite this page

sync-data-firebase skill. Agent Mart. https://agentmart.dev/skills/kotlinfoundation-sync-data-firebase (last updated 2026-10-24)