Make Your App Remember Things with the State SDK
Save user data, game progress, and preferences across sessions — no backend needed. Just tell your AI assistant to use the State SDK.
The Problem: Everything Resets
You built a great app with AI. A quiz, a game, a tool. Someone uses it, has a great time — then closes the tab. When they come back, everything is gone. High score? Gone. Preferences? Gone. That essay they were writing? Gone.
That's how web apps work by default. But it doesn't have to be that way.
The Fix: gapp.so's State SDK
Every app on gapp.so gets a built-in cloud storage system — no backend setup, no database, no API keys. Your app can save and load data with a few lines of code.
The SDK is automatically available in your app as gapp.state. You don't need to install anything.
How to Add It to Your App
Copy this and send it to your AI coding assistant (Claude Code, Cursor, Gemini, etc.):
> "Use gapp.so's state SDK to save and load user data in my app. Here are the docs: https://gapp.so/ai-sdk-prompt.md"
That's it. Your AI assistant will read the documentation and wire everything up for you.
If you want to be more specific, here are some things you can ask for:
- *"Save user preferences so they persist across sessions"*
- *"Add a high score system that remembers each user's best score"*
- *"Auto-save the user's work every few seconds"*
- *"Add a global leaderboard that all users can see"*
What Can It Do?
Save Per-User Data
Each user gets their own private storage. Perfect for:
- Preferences — theme, language, font size
- Progress — game saves, completed levels, unlocked achievements
- Personal content — drafts, notes, custom settings
// Save
await gapp.state.set('preferences', { theme: 'dark', lang: 'zh' })
// Load
const prefs = await gapp.state.get('preferences')Share Data Across All Users
Need a leaderboard? A shared counter? A collaborative space? Use the global scope:
// Read the leaderboard
const scores = await gapp.state.global.get('leaderboard') || []
// Add a new score
scores.push({ name: 'Player1', score: 9500 })
scores.sort((a, b) => b.score - a.score)
await gapp.state.global.set('leaderboard', scores.slice(0, 100))Auto-Save with Zero Effort
Here's the easiest option: if your app already uses localStorage (and your AI assistant probably made it that way), gapp.so automatically syncs it to the cloud. Your users' data follows them across devices — and you don't need to change a single line of code.
// This already works — gapp.so syncs it automatically
localStorage.setItem('gameProgress', JSON.stringify(progress))Three Storage Scopes
| Scope | Who Can Access | Best For |
|---|---|---|
| User | Only that logged-in user, works across devices | Preferences, saves, personal data |
| Session | Only that device (anonymous users) | Temporary state, drafts before login |
| Global | Everyone using the app | Leaderboards, shared content, counters |
By default, the SDK auto-selects: logged-in users get user scope, anonymous users get session scope. You don't need to think about it unless you want to.
Real Examples
A Quiz App That Tracks Progress
window.addEventListener('gapp:ready', async () => {
// Load where the user left off
const progress = await gapp.state.get('quizProgress') || {
currentQuestion: 0,
correctAnswers: 0,
totalAnswered: 0
}
startQuiz(progress)
})
// After each answer
async function onAnswer(isCorrect) {
progress.totalAnswered++
if (isCorrect) progress.correctAnswers++
progress.currentQuestion++
await gapp.state.set('quizProgress', progress)
}A Drawing App with Auto-Save
// Save canvas every 2 seconds after changes
let saveTimer
canvas.addEventListener('change', () => {
clearTimeout(saveTimer)
saveTimer = setTimeout(async () => {
await gapp.state.set('canvas', canvas.toJSON())
}, 2000)
})
// Restore on load
const saved = await gapp.state.get('canvas')
if (saved) canvas.loadFromJSON(saved)Limits
| Limit | |
|---|---|
| User/Session storage | 100 KB per app |
| Global storage | 1 MB per app |
| Max keys | 100 per scope |
| Key length | 100 characters |
These limits are generous for most apps. If you're building something that needs more, consider chunking your data across multiple keys.
User Identity
The SDK also gives you access to user info:
if (gapp.user.isAuthenticated()) {
const name = gapp.user.getName()
const avatar = gapp.user.getAvatarUrl()
showWelcome(name, avatar)
}This is useful for personalizing the experience — showing a welcome message, displaying the user's name on a leaderboard, or customizing the UI.
Test It Locally
Want to test data saving before publishing? Use local development mode:
- Get your dev token from Dashboard > Creator Tools
- Add the dev script to your HTML
- The State SDK works locally with a localStorage-backed mock — same API, no server needed
Details are in the AI SDK prompt docs.
Quick Reference
| I want to... | Tell my AI assistant... |
|---|---|
| Save user data | *"Use gapp.so's state SDK: https://gapp.so/ai-sdk-prompt.md"* |
| Add a leaderboard | *"Add a global leaderboard using gapp.state.global"* |
| Auto-save progress | *"Auto-save user progress with debouncing using gapp.state"* |
| Keep localStorage working | Nothing — it syncs automatically |
| Test locally | *"Set up gapp.so local dev mode: https://gapp.so/ai-sdk-prompt.md"* |
Full Documentation
- State SDK Docs — Full API reference with interactive examples
- AI SDK Prompt — Condensed reference for AI coding tools
- Creator Guide — Overview of everything you can do on gapp.so