vapour

Copyright (c) 2025 Renata Amutio SPDX-License-Identifier: MIT

Vapour - Steamworks SDK Bindings for Gleam

Vapour provides type-safe, idiomatic Gleam bindings for the Steamworks SDK via steamworks-ffi-node.

Features

Quick Start

import gleam/option
import vapour

pub fn main() {
  // Initialize with your app ID (or use 480 for testing with Spacewar)
  let assert Ok(client) = vapour.init(option.Some(480))

  // Run callbacks regularly to keep the connection alive
  vapour.run_callbacks(client)

  // Use the API
  let name = vapour.display_name(client)
  let _result = vapour.write_file(client, "save.dat", "game data")
}

Important Notes

Types

Steam Cloud storage quota information.

pub type CloudQuota {
  CloudQuota(
    total_bytes: Int,
    available_bytes: Int,
    used_bytes: Int,
    percent_used: Float,
  )
}

Constructors

  • CloudQuota(
      total_bytes: Int,
      available_bytes: Int,
      used_bytes: Int,
      percent_used: Float,
    )
pub type Dialog {
  FriendsDialog
  CommunityDialog
  PlayersDialog
  SettingsDialog
  OfficialGameGroupDialog
  StatsDialog
  AchievementsDialog
}

Constructors

  • FriendsDialog
  • CommunityDialog
  • PlayersDialog
  • SettingsDialog
  • OfficialGameGroupDialog
  • StatsDialog
  • AchievementsDialog

Information about a file stored in Steam Cloud.

pub type FileInfo {
  FileInfo(name: String, bytes: Int)
}

Constructors

  • FileInfo(name: String, bytes: Int)

Information about a friend.

pub type FriendInfo {
  FriendInfo(
    steam_id: String,
    persona_name: String,
    persona_state: PersonaState,
  )
}

Constructors

  • FriendInfo(
      steam_id: String,
      persona_name: String,
      persona_state: PersonaState,
    )

Steam friend relationship status.

Describes the relationship between the current user and another Steam user. This includes friend status, pending requests, and blocked users.

pub type FriendRelationship {
  RelationshipNone
  RelationshipBlocked
  RelationshipRequestRecipient
  RelationshipFriend
  RelationshipRequestInitiator
  RelationshipIgnored
  RelationshipIgnoredFriend
  RelationshipSuggested
  RelationshipMax
}

Constructors

  • RelationshipNone

    No relationship

  • RelationshipBlocked

    User has blocked this person

  • RelationshipRequestRecipient

    This person sent you a friend request (pending)

  • RelationshipFriend

    This person is your friend

  • RelationshipRequestInitiator

    You sent this person a friend request (pending)

  • RelationshipIgnored

    You have ignored this person

  • RelationshipIgnoredFriend

    You were friends but now ignored

  • RelationshipSuggested

    Steam suggested this person as a friend

  • RelationshipMax

    Unknown/max relationship value

Opaque type representing a Steam leaderboard.

This handle is obtained from find_leaderboard() or find_or_create_leaderboard() and is used to interact with that specific leaderboard (uploading scores, downloading entries, etc.).

pub type LeaderBoard

Leaderboard data request type.

Specifies which subset of leaderboard entries to download.

pub type LeaderboardDataRequest {
  Global
  GlobalAroundUser
  Friends
}

Constructors

  • Global

    Download the top entries from the entire global leaderboard

  • GlobalAroundUser

    Download entries around the current user’s position

  • Friends

    Download entries for friends only

Leaderboard display type.

Determines how scores are formatted and displayed in the Steam UI.

pub type LeaderboardDisplayType {
  DisplayNone
  Numeric
  TimeSeconds
  TimeMilliseconds
}

Constructors

  • DisplayNone

    No special display format

  • Numeric

    Display as a plain number (e.g., “12345”)

  • TimeSeconds

    Display as time in seconds (e.g., “1:23.45”)

  • TimeMilliseconds

    Display as time in milliseconds (e.g., “1:23.456”)

Leaderboard entry.

pub type LeaderboardEntry {
  LeaderboardEntry(
    steam_id: String,
    global_rank: Int,
    score: Int,
  )
}

Constructors

  • LeaderboardEntry(steam_id: String, global_rank: Int, score: Int)

Leaderboard sort method.

Determines how leaderboard entries are ranked.

pub type LeaderboardSortMethod {
  SortNone
  Ascending
  Descending
}

Constructors

  • SortNone

    No sorting

  • Ascending

    Lower scores are better (e.g., speedruns, golf scores)

  • Descending

    Higher scores are better (e.g., high scores, points)

Steam user’s online status (persona state).

This represents the current online status that a user has set in Steam. The status is visible to friends and affects how the user appears in friend lists.

pub type PersonaState {
  Offline
  Online
  Busy
  Away
  Snooze
  LookingToTrade
  LookingToPlay
  Invisible
  Max
}

Constructors

  • Offline

    User is offline or appear offline

  • Online

    User is online and available

  • Busy

    User is online but busy (Do Not Disturb)

  • Away

    User is away from keyboard

  • Snooze

    User is snoozing/sleeping

  • LookingToTrade

    User is looking to trade items

  • LookingToPlay

    User is looking for people to play with

  • Invisible

    User is online but invisible to others

  • Max

    Unknown/max state value

Steam API status information.

pub type Status {
  Status(is_initialized: Bool, app_id: Int, steam_id: String)
}

Constructors

  • Status(is_initialized: Bool, app_id: Int, steam_id: String)
pub type SteamId {
  SteamId(String)
}

Constructors

  • SteamId(String)

Opaque type representing a connected Steamworks client.

This is obtained by calling init() and is required for all other API calls.

pub type SteamworksClient

Leaderboard score upload method.

Determines how new scores are handled when uploading to a leaderboard.

pub type UploadScoreMethod {
  KeepBest
  ForceUpdate
}

Constructors

  • KeepBest

    Only update if the new score is better than the current score

  • ForceUpdate

    Always update, regardless of whether it’s better or worse

Values

pub fn achievement_achieved_percent(
  client: SteamworksClient,
  achievement: String,
) -> promise.Promise(Result(Float, Nil))

Get global unlock percentage for an achievement (async).

Returns what percentage of all players have unlocked this achievement (0-100). Must call request_global_achievement_percentages() first.

Example

import gleam/javascript/promise

use request_successful <- promise.await(
  vapour.request_global_achievement_percentages(client),
)
case request_successful {
  True -> {
    vapour.achievement_achieved_percent(client, "ACH_WIN_ONE_GAME")
    |> promise.await(fn(result) {
      case result {
        Ok(percent) ->
          io.println(float.to_string(percent) <> "% of players have this")
        Error(_) -> io.println("Data not available")
      }
      promise.resolve(Nil)
    })
  }
  False -> promise.resolve(Nil)
}
pub fn activate_dialog(
  client: SteamworksClient,
  dialog: Dialog,
) -> Nil

Activate a Steam overlay dialog.

Opens the Steam overlay to a specific dialog.

Example

// Open achievements dialog
vapour.activate_dialog(client, AchievementsDialog)

// Open friends list
vapour.activate_dialog(client, FriendsDialog)
pub fn activate_store(
  client: SteamworksClient,
  app_id: Int,
) -> Nil

Activate the Steam overlay to a store page.

Opens the Steam store to the specified app’s page.

Parameters

  • app_id: The Steam App ID to show in the store

Example

// Open your game's DLC store page
vapour.activate_store(client, 12345)

// Open your game's main store page
vapour.activate_store(client, YOUR_APP_ID)
pub fn activate_user_page_dialog(
  client: SteamworksClient,
  steam_id: SteamId,
) -> Nil

Activate the Steam overlay to a specific user’s profile.

Parameters

  • steam_id The user’s Steam ID

Example

// Open a friend's profile
vapour.activate_user_page_dialog(client, steam_id)
pub fn activate_web_page(
  client: SteamworksClient,
  url: String,
) -> Nil

Activate the Steam overlay browser to a web page.

Opens the specified URL in the Steam overlay browser.

Example

// Open game website
vapour.activate_web_page(client, "https://mygame.com")

// Open wiki page
vapour.activate_web_page(client, "https://wiki.mygame.com/walkthrough")
pub fn all_friends(client: SteamworksClient) -> List(FriendInfo)

Get all friends with their information.

Returns a list of all friends with their Steam ID, name, and online status.

Example

let friends = vapour.all_friends(client)
list.each(friends, fn(friend) {
  io.println(friend.persona_name <> " (" <> friend.steam_id <> ")")
})
pub fn clear_rich_presence(client: SteamworksClient) -> Nil

Clear all Rich Presence data.

Removes all Rich Presence information for the current player. Friends will no longer see detailed status about what you’re doing in the game.

Call this when the player exits your game or when you want to hide their current activity.

Example

// Clear rich presence when exiting game
vapour.clear_rich_presence(client)
pub fn cloud_enabled_for_account(
  client: SteamworksClient,
) -> Bool

Check if Steam Cloud is enabled for the current user’s account.

Returns True if the user has Steam Cloud enabled in their Steam settings.

Example

case vapour.cloud_enabled_for_account(client) {
  True -> io.println("Cloud enabled for account")
  False -> io.println("Cloud disabled - user must enable it in Steam settings")
}
pub fn cloud_enabled_for_app(client: SteamworksClient) -> Bool

Check if Steam Cloud is enabled for the current app.

Returns True if Steam Cloud is enabled for this app. This can be toggled using toggle_cloud_for_app().

pub fn cloud_quota(client: SteamworksClient) -> CloudQuota

Get Steam Cloud storage quota information.

Returns detailed information about cloud storage usage including total, available, and used bytes, plus the percentage used.

Important: This helps prevent “out of space” errors when saving files. Always check available space before writing large files to Steam Cloud.

Example

let quota = vapour.cloud_quota(client)

io.println("Cloud Storage:")
io.println("  Total: " <> int.to_string(quota.total_bytes) <> " bytes")
io.println("  Used: " <> int.to_string(quota.used_bytes) <> " bytes")
io.println("  Available: " <> int.to_string(quota.available_bytes) <> " bytes")
io.println("  Usage: " <> float.to_string(quota.percent_used) <> "%")

// Check before saving
let save_size = 1_000_000  // 1 MB
case quota.available_bytes > save_size {
  True -> vapour.write_file(client, "savegame.dat", save_data)
  False -> io.println("Not enough cloud storage space!")
}
pub fn coplay_friend(
  client: SteamworksClient,
  index: Int,
) -> String

Get a coplay friend by index.

Use this with coplay_friend_count() to iterate through all friends you’ve recently played with.

Parameters

  • index: Zero-based index (0 to coplay_friend_count() - 1)

Returns

The Steam ID of the coplay friend at the specified index.

Example

let count = vapour.coplay_friend_count(client)
let first_coplay_friend = vapour.coplay_friend(client, 0)
io.println("Recently played with: " <> first_coplay_friend)
pub fn coplay_friend_count(client: SteamworksClient) -> Int

Get the count of coplay friends.

What is Coplay? “Coplay” refers to Steam users you have recently played multiplayer games with. Steam tracks which friends you’ve played together with in the same game session, and this data is used to suggest friends to play with and show recent gaming partners.

Returns the number of friends in your coplay list (friends you’ve recently played with).

Example

let coplay_count = vapour.coplay_friend_count(client)
io.println("You've recently played with " <> int.to_string(coplay_count) <> " friends")
pub fn delete_file(
  client: SteamworksClient,
  name: String,
) -> Bool

Delete a file from Steam Cloud.

Returns True if the file was successfully deleted, False otherwise.

Example

case vapour.delete_file(client, "old_save.dat") {
  True -> io.println("File deleted")
  False -> io.println("Failed to delete file")
}
pub fn display_name(client: SteamworksClient) -> String

Get the local player’s display name (persona name).

Returns the Steam display name that other users see.

Example

let name = vapour.display_name(client)
io.println("Welcome, " <> name <> "!")
pub fn do_activate_user_page_dialog(
  client: SteamworksClient,
  dialog: String,
  steam_id_64: String,
) -> Nil
pub fn download_scores(
  client: SteamworksClient,
  leaderboard_handle: LeaderBoard,
  data_request: LeaderboardDataRequest,
  start: Int,
  end: Int,
) -> promise.Promise(List(LeaderboardEntry))

Download leaderboard entries (async).

pub fn file_exists(
  client: SteamworksClient,
  name: String,
) -> Bool

Check if a file exists in Steam Cloud.

Returns True if the file exists, False otherwise.

Example

case vapour.file_exists(client, "savegame.json") {
  True -> load_save_file(client)
  False -> create_new_game()
}
pub fn find_leaderboard(
  client: SteamworksClient,
  leaderboard_name: String,
) -> promise.Promise(Result(LeaderBoard, Nil))

Find a leaderboard by name (async).

Returns a leaderboard handle, or Error(Nil) if not found.

pub fn find_or_create_leaderboard(
  client: SteamworksClient,
  name: String,
  sort_method: LeaderboardSortMethod,
  display_type: LeaderboardDisplayType,
) -> promise.Promise(Result(LeaderBoard, Nil))

Find or create a leaderboard with sort and display settings (async).

Searches for a leaderboard by name and creates it if it doesn’t exist. Allows you to specify how scores are sorted and displayed.

Parameters

  • name: Leaderboard name (max 128 UTF-8 bytes)
  • sort_method: How entries should be sorted (Ascending for times, Descending for scores)
  • display_type: How scores should be displayed (Numeric, TimeSeconds, etc.)

Returns

A Promise that resolves to Ok(leaderboard) or Error(Nil).

Example

import gleam/javascript/promise
import vapour.{Descending, Numeric}

// Create a high score leaderboard
vapour.find_or_create_leaderboard(client, "HighScores", Descending, Numeric)
|> promise.await(fn(result) {
  case result {
    Ok(leaderboard) -> io.println("Leaderboard ready")
    Error(_) -> io.println("Failed to create leaderboard")
  }
  promise.resolve(Nil)
})

// Create a speedrun leaderboard (lower time is better)
vapour.find_or_create_leaderboard(client, "Speedrun", Ascending, TimeSeconds)
|> promise.await(fn(result) {
  case result {
    Ok(lb) -> io.println("Speedrun leaderboard ready")
    Error(_) -> io.println("Failed")
  }
  promise.resolve(Nil)
})
pub fn friend_coplay_game(
  client: SteamworksClient,
  steam_id: String,
) -> Int

Get which game you last played with a specific user.

Returns the Steam App ID of the game you most recently played together. Returns 0 if you’ve never played together or the data is unavailable.

Example

let app_id = vapour.friend_coplay_game(client, friend_id)
case app_id {
  0 -> io.println("No coplay game")
  _ -> io.println("Last played together in App ID: " <> int.to_string(app_id))
}
pub fn friend_coplay_time(
  client: SteamworksClient,
  steam_id: String,
) -> Int

Get when you last played with a specific user.

Returns a Unix timestamp (seconds since January 1, 1970) of when you last played a multiplayer game together with this friend. Returns 0 if you’ve never played together or the data is unavailable.

Example

let timestamp = vapour.friend_coplay_time(client, friend_id)
case timestamp {
  0 -> io.println("Never played together")
  _ -> io.println("Last played together: " <> int.to_string(timestamp))
}
pub fn friend_count(client: SteamworksClient) -> Int

Get the count of friends.

Returns the total number of friends in your friends list.

Example

let count = vapour.friend_count(client)
io.println("You have " <> int.to_string(count) <> " friends")
pub fn friend_game_played(
  client: SteamworksClient,
  steam_id: String,
) -> Result(Int, Nil)

Get the game a friend is currently playing.

Returns the App ID of the game the friend is playing, or Error(Nil) if not playing.

Example

case vapour.friend_game_played(client, friend_id) {
  Ok(app_id) -> io.println("Friend is playing App " <> int.to_string(app_id))
  Error(_) -> io.println("Friend is not playing any game")
}
pub fn friend_persona_name(
  client: SteamworksClient,
  steam_id: String,
) -> String

Get a friend’s persona name (display name).

Returns the friend’s Steam display name.

Example

let name = vapour.friend_persona_name(client, "76561197960287930")
io.println("Friend name: " <> name)
pub fn friend_persona_state(
  client: SteamworksClient,
  steam_id: String,
) -> PersonaState

Get a friend’s persona state (online status).

Returns the friend’s current online status.

Example

let state = vapour.friend_persona_state(client, friend_id)
case state {
  vapour.Online -> io.println("Friend is online")
  vapour.Offline -> io.println("Friend is offline")
  _ -> io.println("Friend has other status")
}
pub fn friend_relationship(
  client: SteamworksClient,
  steam_id: String,
) -> FriendRelationship

Get the relationship with another user.

pub fn friend_steam_level(
  client: SteamworksClient,
  steam_id: String,
) -> Int

Get a friend’s Steam level.

Returns the friend’s Steam level (0 if unavailable).

Example

let level = vapour.friend_steam_level(client, friend_id)
io.println("Friend is Level " <> int.to_string(level))
pub fn global_stat_float(
  client: SteamworksClient,
  stat_name: String,
) -> promise.Promise(Result(Float, Nil))

Get a global float stat (async).

pub fn global_stat_int(
  client: SteamworksClient,
  stat_name: String,
) -> promise.Promise(Result(Int, Nil))

Get a global integer stat (async).

pub fn indicate_achievement_progress(
  client: SteamworksClient,
  achievement: String,
  current_progress: Int,
  max_progress: Int,
) -> promise.Promise(Bool)

Show achievement progress notification (async).

Displays a progress notification in the Steam overlay (e.g., “Win 50 games: 25/50”). Useful for achievements that require multiple steps.

Parameters

  • achievement: Achievement API name
  • current_progress: Current progress value
  • max_progress: Maximum progress value needed to unlock

Example

import gleam/javascript/promise

vapour.indicate_achievement_progress(client, "ACH_WIN_50_GAMES", 25, 50)
|> promise.await(fn(success) {
  case success {
    True -> io.println("Progress notification shown")
    False -> io.println("Failed to show progress")
  }
  promise.resolve(Nil)
})
pub fn init(
  app_id: option.Option(Int),
) -> Result(SteamworksClient, Nil)

Initialize the Steamworks API.

This must be called before using any other Steamworks functionality. Steam must be running for initialization to succeed.

Parameters

  • app_id: Your Steam App ID. Pass option.None to read from a steam_appid.txt file in the current directory. Use option.Some(480) for testing with Spacewar (Steam’s test app).

Returns

  • Ok(client): Successfully initialized. Use this client for all API calls.
  • Error(Nil): Initialization failed (Steam not running or invalid app ID).

Example

import gleam/option
import vapour

// Initialize with your app ID
let assert Ok(client) = vapour.init(option.Some(YOUR_APP_ID))

// Or use Spacewar for testing
let assert Ok(client) = vapour.init(option.Some(480))

// Or read from steam_appid.txt
let assert Ok(client) = vapour.init(option.None)
pub fn invite_friends_to_lobby(
  client: SteamworksClient,
  lobby_steam_id: String,
) -> Nil

Open the Steam overlay invite dialog for a lobby.

Opens the invite dialog where players can select friends to invite to the specified lobby. Essential for multiplayer games.

Parameters

  • lobby_steam_id: The Steam ID of the lobby to invite friends to

Example

// Open invite dialog for a lobby
vapour.invite_friends_to_lobby(client, "109775241021923456")
pub fn invite_friends_with_connect_string(
  client: SteamworksClient,
  connect_string: String,
) -> Nil

Open the Steam overlay invite dialog with a custom connect string.

Opens the invite dialog and sends the connect string with the invitation. When friends accept, they receive this connect string (e.g., server IP, session ID).

Parameters

  • connect_string: Custom connection information (e.g., “+connect 192.168.1.100:27015”)

Example

// Invite with server connection info
let connect_str = "+connect 192.168.1.100:27015"
vapour.invite_friends_with_connect_string(client, connect_str)

// Invite with session ID
let connect_str = "+join_session abc123-def456"
vapour.invite_friends_with_connect_string(client, connect_str)
pub fn is_achievement_unlocked(
  client: SteamworksClient,
  achievement: String,
) -> promise.Promise(Bool)

Check if an achievement is unlocked (async).

Returns a Promise that resolves to True if the achievement is unlocked, False otherwise.

Example

import gleam/javascript/promise

vapour.is_achievement_unlocked(client, "ACH_WIN_ONE_GAME")
|> promise.await(fn(is_unlocked) {
  case is_unlocked {
    True -> io.println("Already unlocked")
    False -> io.println("Not yet unlocked")
  }
  promise.resolve(Nil)
})
pub fn leaderboard_display_type(
  leaderboard_handle: LeaderBoard,
) -> LeaderboardDisplayType

Get the display type of a leaderboard.

Returns how scores should be displayed (Numeric, TimeSeconds, etc.).

Example

use result <- promise.await(vapour.find_leaderboard(client, "Speedrun"))
case result {
  Ok(leaderboard) -> {
    let display = vapour.leaderboard_display_type(client, leaderboard)
    case display {
      vapour.TimeSeconds -> io.println("Scores shown as time in seconds")
      vapour.Numeric -> io.println("Scores shown as numbers")
      _ -> io.println("Other display format")
    }
  }
  Error(_) -> io.println("Leaderboard not found")
}
pub fn leaderboard_entry_count(
  leaderboard_handle: LeaderBoard,
) -> Int

Get the entry count for a leaderboard.

Returns the total number of entries (scores) in the leaderboard.

Example

use result <- promise.await(vapour.find_leaderboard(client, "HighScores"))
case result {
  Ok(leaderboard) -> {
    let count = vapour.leaderboard_entry_count(client, leaderboard)
    io.println("Leaderboard has " <> int.to_string(count) <> " entries")
  }
  Error(_) -> io.println("Leaderboard not found")
}
pub fn leaderboard_name(
  leaderboard_handle: LeaderBoard,
) -> String

Get the name of a leaderboard.

Returns the leaderboard’s name as configured in Steam.

Example

use result <- promise.await(vapour.find_leaderboard(client, "HighScores"))
case result {
  Ok(leaderboard) -> {
    let name = vapour.leaderboard_name(client, leaderboard)
    io.println("Leaderboard name: " <> name)
  }
  Error(_) -> io.println("Leaderboard not found")
}
pub fn leaderboard_sort_method(
  leaderboard_handle: LeaderBoard,
) -> LeaderboardSortMethod

Get the sort method of a leaderboard.

Returns how the leaderboard entries are sorted (Ascending, Descending, or None).

Example

use result <- promise.await(vapour.find_leaderboard(client, "Speedrun"))
case result {
  Ok(leaderboard) -> {
    let sort_method = vapour.leaderboard_sort_method(client, leaderboard)
    case sort_method {
      vapour.Ascending -> io.println("Lower scores are better")
      vapour.Descending -> io.println("Higher scores are better")
      _ -> io.println("No sorting")
    }
  }
  Error(_) -> io.println("Leaderboard not found")
}
pub fn list_achievements(
  client: SteamworksClient,
) -> promise.Promise(List(String))

Get a list of all achievement names (async).

Returns a Promise that resolves to a list of all achievement IDs defined for this app.

Example

import gleam/javascript/promise
import gleam/list

vapour.list_achievements(client)
|> promise.await(fn(achievements) {
  io.println("Found " <> int.to_string(list.length(achievements)) <> " achievements")
  list.each(achievements, io.println)
  promise.resolve(Nil)
})
pub fn list_files(client: SteamworksClient) -> List(FileInfo)

List all files in Steam Cloud.

Returns a list of FileInfo records containing file names and sizes in bytes.

Example

let files = vapour.list_files(client)
list.each(files, fn(file) {
  io.println(file.name <> ": " <> int.to_string(file.bytes) <> " bytes")
})
pub fn lock_achievement(
  client: SteamworksClient,
  achievement: String,
) -> promise.Promise(Bool)

Lock an achievement (async) - primarily for testing.

Returns a Promise that resolves to True if the achievement was successfully locked, False otherwise.

Example

import gleam/javascript/promise

vapour.lock_achievement(client, "ACH_WIN_ONE_GAME")
|> promise.await(fn(success) {
  case success {
    True -> io.println("Achievement locked for testing")
    False -> io.println("Failed to lock achievement")
  }
  promise.resolve(Nil)
})
pub fn number_of_current_players(
  client: SteamworksClient,
) -> promise.Promise(Result(Int, Nil))

Get the number of players currently playing the game (async).

Returns a Promise that resolves to the player count, or Error(Nil) on error.

Example

import gleam/javascript/promise

vapour.number_of_current_players(client)
|> promise.await(fn(result) {
  case result {
    Ok(count) -> io.println(int.to_string(count) <> " players online!")
    Error(_) -> io.println("Failed to get player count")
  }
  promise.resolve(Nil)
})
pub fn persona_state(client: SteamworksClient) -> PersonaState

Get the current user’s persona state (online status).

Returns the user’s current online status.

Example

let state = vapour.persona_state(client)
case state {
  vapour.Online -> io.println("You are online")
  vapour.Offline -> io.println("You appear offline")
  _ -> io.println("Other status")
}
pub fn read_file(
  client: SteamworksClient,
  name: String,
) -> String

Read a file from Steam Cloud.

Returns the file contents as a string, or an empty string if the file doesn’t exist or the read fails.

Example

let content = vapour.read_file(client, "savegame.json")
case content {
  "" -> io.println("File not found")
  data -> process_save_data(data)
}
pub fn request_global_achievement_percentages(
  client: SteamworksClient,
) -> promise.Promise(Bool)

Request global achievement unlock percentages (async).

Must be called before using achievement_achieved_percent(). Returns True if the request was sent successfully.

Example

import gleam/javascript/promise

vapour.request_global_achievement_percentages(client)
|> promise.await(fn(success) {
  case success {
    True -> io.println("Global data requested")
    False -> io.println("Request failed")
  }
  promise.resolve(Nil)
})
pub fn request_global_stats(
  client: SteamworksClient,
  history_days: Int,
) -> promise.Promise(Bool)

Request global stats from Steam (async).

Must be called before getting global stats. Returns True if request sent successfully.

pub fn request_user_stats(
  client: SteamworksClient,
  steam_id: String,
) -> promise.Promise(Bool)

Request stats for another user (async).

pub fn run_callbacks(client: SteamworksClient) -> Nil

Run Steam callbacks to process pending events.

This should be called regularly (ideally every frame or every 100ms) to keep the Steam connection alive and process asynchronous operations.

Example

import vapour

pub fn game_loop(client: vapour.SteamworksClient) {
  // Process Steam callbacks each frame
  vapour.run_callbacks(client)

  // Rest of your game loop...
}
pub fn running_steam(client: SteamworksClient) -> Bool

Check if the Steam client is running.

Returns True if Steam is currently running on the system, False otherwise.

Example

import vapour

case vapour.running_steam(client) {
  True -> io.println("Steam is running")
  False -> io.println("Steam is not running")
}
pub fn set_rich_presence(
  client: SteamworksClient,
  key: String,
  value: String,
) -> Nil

Set a Rich Presence key/value pair.

What is Rich Presence? Rich Presence is a Steam feature that allows your game to display detailed information about what players are currently doing. This information appears in the Steam friends list, chat, and on user profiles. It helps friends see at a glance what you’re up to in the game (e.g., “In Multiplayer Lobby”, “Playing Campaign - Level 5”, “Score: 12,500 points”).

You can set multiple key/value pairs to provide detailed status information. Steam will format and display this data according to your game’s Rich Presence configuration in the Steamworks partner site.

Parameters

  • key: Rich Presence key (e.g., “status”, “score”, “level”, “steam_display”)
  • value: Rich Presence value (e.g., “In Menu”, “1000”, “Level 3”)

Common Keys

  • "steam_display": Controls which localization token to use for display
  • "status": Current game mode or activity
  • "score": Player’s current score
  • "level": Current level or map name

Example

// Set player status
vapour.set_rich_presence(client, "status", "In Main Menu")

// Set current level
vapour.set_rich_presence(client, "level", "Level 3")

// Set score
vapour.set_rich_presence(client, "score", "1500")

// Tell Steam which display format to use
vapour.set_rich_presence(client, "steam_display", "#Status_Playing")
pub fn set_stat_float(
  client: SteamworksClient,
  stat_name: String,
  value: Float,
) -> promise.Promise(Bool)

Set a float stat value for the current user (async).

Returns a Promise that resolves to True if successful, False otherwise.

Example

import gleam/javascript/promise

vapour.set_stat_float(client, "accuracy", 0.85)
|> promise.await(fn(success) {
  case success {
    True -> io.println("Stat updated!")
    False -> io.println("Failed to update stat")
  }
  promise.resolve(Nil)
})
pub fn set_stat_int(
  client: SteamworksClient,
  stat_name: String,
  value: Int,
) -> promise.Promise(Bool)

Set an integer stat value for the current user (async).

Returns a Promise that resolves to True if successful, False otherwise.

Example

import gleam/javascript/promise

vapour.set_stat_int(client, "total_kills", 100)
|> promise.await(fn(success) {
  case success {
    True -> io.println("Stat updated!")
    False -> io.println("Failed to update stat")
  }
  promise.resolve(Nil)
})
pub fn stat_float(
  client: SteamworksClient,
  stat_name: String,
) -> promise.Promise(Result(Float, Nil))

Get a float stat value for the current user (async).

Returns a Promise that resolves to the stat value, or Error(Nil) if not found.

Example

import gleam/javascript/promise

vapour.stat_float(client, "accuracy")
|> promise.await(fn(result) {
  case result {
    Ok(accuracy) -> io.println("Accuracy: " <> float.to_string(accuracy))
    Error(_) -> io.println("Stat not found")
  }
  promise.resolve(Nil)
})
pub fn stat_int(
  client: SteamworksClient,
  stat_name: String,
) -> promise.Promise(Result(Int, Nil))

Get an integer stat value for the current user (async).

Returns a Promise that resolves to the stat value, or Error(Nil) if not found.

Example

import gleam/javascript/promise

vapour.stat_int(client, "total_kills")
|> promise.await(fn(result) {
  case result {
    Ok(kills) -> io.println("Total kills: " <> int.to_string(kills))
    Error(_) -> io.println("Stat not found")
  }
  promise.resolve(Nil)
})
pub fn status(client: SteamworksClient) -> Status

Get Steam API status including Steam ID and connection state.

Returns information about the current Steam connection including the logged-in user’s Steam ID.

Example

import vapour
import gleam/io

let status = vapour.status(client)
io.println("Steam ID: " <> status.steam_id)
io.println("Connected: " <> bool.to_string(status.is_initialized))
pub fn toggle_cloud_for_app(
  client: SteamworksClient,
  enabled: Bool,
) -> Nil

Enable or disable Steam Cloud for the current app.

Parameters

  • enabled: True to enable cloud storage, False to disable it

Example

// Enable cloud storage
vapour.toggle_cloud_for_app(client, True)

// Disable cloud storage
vapour.toggle_cloud_for_app(client, False)
pub fn total_achievement_count(
  client: SteamworksClient,
) -> promise.Promise(Int)

Get the total number of achievements configured for this game (async).

Returns the count of all achievements defined in the Steamworks Partner site, including both locked and unlocked achievements.

Example

import gleam/javascript/promise

vapour.total_achievement_count(client)
|> promise.await(fn(total) {
  io.println("This game has " <> int.to_string(total) <> " achievements")
  promise.resolve(Nil)
})
pub fn unlock_achievement(
  client: SteamworksClient,
  achievement: String,
) -> promise.Promise(Bool)

Unlock an achievement (async).

Returns a Promise that resolves to True if the achievement was successfully unlocked, False otherwise.

Example

import gleam/javascript/promise

vapour.unlock_achievement(client, "ACH_WIN_ONE_GAME")
|> promise.await(fn(success) {
  case success {
    True -> io.println("Achievement unlocked!")
    False -> io.println("Failed to unlock achievement")
  }
  promise.resolve(Nil)
})
pub fn unlocked_achievement_count(
  client: SteamworksClient,
) -> promise.Promise(Int)

Get the number of achievements the user has unlocked (async).

Returns the count of achievements the current user has unlocked. Useful for displaying progress like “15/50 achievements unlocked”.

Example

import gleam/javascript/promise

// Show achievement progress
use total <- promise.await(vapour.total_achievement_count(client))
use unlocked <- promise.await(vapour.unlocked_achievement_count(client))

let percent = case total {
  0 -> 0.0
  _ -> int.to_float(unlocked) /. int.to_float(total) *. 100.0
}

io.println(
  "Progress: "
  <> int.to_string(unlocked)
  <> "/"
  <> int.to_string(total)
  <> " ("
  <> float.to_string(percent)
  <> "%)",
)
promise.resolve(Nil)
pub fn update_avg_rate_stat(
  client: SteamworksClient,
  stat_name: String,
  count_this_session: Int,
  session_length: Int,
) -> promise.Promise(Bool)

Update an average rate stat (async).

For stats like “kills per hour”, Steam maintains the average calculation.

pub fn upload_score(
  client: SteamworksClient,
  leaderboard_handle: LeaderBoard,
  score: Int,
  upload_method: UploadScoreMethod,
) -> promise.Promise(Bool)

Upload a score to a leaderboard (async).

pub fn user_stat_float(
  client: SteamworksClient,
  steam_id: String,
  stat_name: String,
) -> promise.Promise(Result(Float, Nil))

Get a float stat for another user (async).

pub fn user_stat_int(
  client: SteamworksClient,
  steam_id: String,
  stat_name: String,
) -> promise.Promise(Result(Int, Nil))

Get an integer stat for another user (async).

pub fn write_file(
  client: SteamworksClient,
  name: String,
  content: String,
) -> Bool

Write a file to Steam Cloud.

Parameters

  • name: Filename to write (e.g., “savegame.json”)
  • content: File content as a string

Returns

True if the write was successful, False otherwise.

Example

let save_data = json.encode(game_state)
case vapour.write_file(client, "savegame.json", save_data) {
  True -> io.println("Game saved to cloud")
  False -> io.println("Failed to save to cloud")
}
Search Document