add .env-based config, token script, and VS Code launch configs

Move Twitch credentials from hardcoded launch.json args to a gitignored
.env file read via --dart-define-from-file. Add a shell script to get a
user auth token through the Authorization Code flow for easy emulator
login. Update README with the new setup steps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Tommy Chow 2026-03-01 20:09:39 -08:00
parent 6b765e4246
commit 09b3b3543b
5 changed files with 130 additions and 3 deletions

2
.env.example Normal file
View file

@ -0,0 +1,2 @@
CLIENT_ID=
SECRET=

5
.gitignore vendored
View file

@ -21,7 +21,7 @@ migrate_working_dir/
# The .vscode folder contains launch configuration and tasks you configure in # The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line # VS Code which you may wish to be included in version control, so this line
# is commented out by default. # is commented out by default.
.vscode/ # .vscode/
# Flutter/Dart/Pub related # Flutter/Dart/Pub related
**/doc/api/ **/doc/api/
@ -64,5 +64,8 @@ random/
# potentially sensitive review information # potentially sensitive review information
**/fastlane/metadata/review_information **/fastlane/metadata/review_information
# secrets
.env
# ai # ai
.claude/settings.local.json .claude/settings.local.json

25
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,25 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "frosty",
"request": "launch",
"type": "dart",
"args": ["--dart-define-from-file=.env"]
},
{
"name": "frosty (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile",
"args": ["--dart-define-from-file=.env"]
},
{
"name": "frosty (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release",
"args": ["--dart-define-from-file=.env"]
}
]
}

View file

@ -85,11 +85,17 @@ For a more detailed overview, visit [frostyapp.io](https://www.frostyapp.io/).
3. Go to the [Twitch dev console](https://dev.twitch.tv/login) and register a new application to retrieve a **Client ID** and **Client Secret**. 3. Go to the [Twitch dev console](https://dev.twitch.tv/login) and register a new application to retrieve a **Client ID** and **Client Secret**.
4. Use [`--dart-define`](https://dartcode.org/docs/using-dart-define-in-flutter/) to set the `clientId` and `secret` environment variables with your **Client ID** and **Client Secret**. 4. Copy `.env.example` to `.env` and fill in your credentials:
```bash
cp .env.example .env
```
5. Run `flutter pub get` to fetch all the dependencies. 5. Run `flutter pub get` to fetch all the dependencies.
6. Choose an emulator or device and run the app! 6. Choose an emulator or device and run the app! The included VS Code launch configurations will automatically read your `.env` file.
7. (Optional) Run `./scripts/get-twitch-token.sh` to quickly get a user auth token. Long-press the **Anonymous** account tile in the app to log in from your clipboard.
> [!IMPORTANT] > [!IMPORTANT]
> Frosty uses [MobX](https://mobx.netlify.app/) for state management. Please refer to the documentation about code generation, otherwise your changes within MobX stores may not be applied. > Frosty uses [MobX](https://mobx.netlify.app/) for state management. Please refer to the documentation about code generation, otherwise your changes within MobX stores may not be applied.

91
scripts/get-twitch-token.sh Executable file
View file

@ -0,0 +1,91 @@
#!/bin/bash
#
# Gets a Twitch OAuth user token for emulator testing.
#
# Usage: ./scripts/get-twitch-token.sh
#
# Reads CLIENT_ID and SECRET from .env, env vars, or prompts interactively.
# Opens the Twitch OAuth page in your browser — after you authorize,
# paste the redirect URL back here and the token is copied to your clipboard.
# Then long-press the Anonymous account tile in the app to log in.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
ENV_FILE="$PROJECT_DIR/.env"
load_env_var() {
local name="$1"
local current="${!name:-}"
if [ -n "$current" ]; then
return
fi
if [ -f "$ENV_FILE" ] && grep -q "^${name}=" "$ENV_FILE"; then
eval "$name=$(grep "^${name}=" "$ENV_FILE" | cut -d= -f2-)"
return
fi
read -rp "$name: " "$name"
}
load_env_var CLIENT_ID
load_env_var SECRET
if [ -z "${CLIENT_ID:-}" ] || [ -z "${SECRET:-}" ]; then
echo "Error: CLIENT_ID and SECRET are both required."
echo "Add them to .env or export them in your shell."
exit 1
fi
SCOPES="chat:read+chat:edit+user:read:follows+user:read:blocked_users+user:manage:blocked_users+user:manage:chat_color"
REDIRECT_URI="https://twitch.tv/login"
URL="https://id.twitch.tv/oauth2/authorize?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=${SCOPES}&force_verify=true"
echo "Opening Twitch authorization in your browser..."
open "$URL"
echo ""
echo "After authorizing, copy the full URL from the address bar and paste it here:"
echo "(it will look like https://twitch.tv/login?code=...)"
echo ""
read -rp "> " REDIRECT_URL
# Extract the authorization code from the redirect URL query params
CODE=$(echo "$REDIRECT_URL" | sed -n 's/.*[?&]code=\([^&]*\).*/\1/p')
if [ -z "$CODE" ]; then
echo ""
echo "Error: could not extract code from that URL."
echo "Make sure you pasted the full URL including the ?code=... part."
exit 1
fi
# Exchange the authorization code for an access token
echo ""
echo "Exchanging code for token..."
RESPONSE=$(curl -s -X POST "https://id.twitch.tv/oauth2/token" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${SECRET}" \
-d "code=${CODE}" \
-d "grant_type=authorization_code" \
-d "redirect_uri=${REDIRECT_URI}")
# Try to extract access_token from JSON response
TOKEN=$(echo "$RESPONSE" | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)
if [ -z "$TOKEN" ]; then
echo "Error: token exchange failed."
echo "$RESPONSE"
exit 1
fi
echo "$TOKEN" | tr -d '\n' | pbcopy
echo "Token copied to clipboard!"
echo ""
echo "Now in the emulator, long-press the Anonymous account tile to log in."