Last active
September 9, 2025 17:57
-
-
Save ergosteur/ef4dba76a099178402830b8d41cfee12 to your computer and use it in GitHub Desktop.
Firefox SSB Creator - Linux Firefox "Web App"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # --- Script to create a Firefox Single-Site Browser (SSB) --- | |
| # V8: Implements a slim, auto-hiding toolbar instead of a fully hidden one. | |
| # Original idea /u/Apoema - https://www.reddit.com/r/firefox/comments/li2lqg/comment/gn2sltw/ | |
| # Made with AI assistance in case you couldn't tell by the excessive use of emoji. | |
| echo "π₯ Firefox SSB Creator (v8) π₯" | |
| echo "------------------------------" | |
| # --- 1. Check for Dependencies --- | |
| if ! command -v firefox &> /dev/null; then | |
| echo "β Error: 'firefox' is not installed or not in your PATH." >&2 | |
| exit 1 | |
| fi | |
| if ! command -v curl &> /dev/null; then | |
| echo "β Error: 'curl' is not installed or not in your PATH." >&2 | |
| exit 1 | |
| fi | |
| # ============================================================================== | |
| # --- STAGE 1: GATHER ALL USER INPUT --- | |
| # ============================================================================== | |
| echo "Step 1: Please provide the application details." | |
| read -p " Enter the name for your application (e.g., Google Calendar): " APP_NAME | |
| if [[ -z "$APP_NAME" ]]; then | |
| echo "β Error: Application name cannot be empty." >&2 | |
| exit 1 | |
| fi | |
| read -p " Enter the full URL (e.g., https://calendar.google.com): " APP_URL | |
| if [[ -z "$APP_URL" ]]; then | |
| echo "β Error: URL cannot be empty." >&2 | |
| exit 1 | |
| fi | |
| echo "" | |
| echo "Step 2: Please choose an icon for the application." | |
| read -p " [A]uto-detect (default), [U]RL, system [N]ame, or [S]kip? " ICON_CHOICE | |
| case ${ICON_CHOICE^^} in | |
| U) | |
| ICON_MODE="URL" | |
| read -p " Enter the URL for the icon image: " ICON_DATA | |
| ;; | |
| N) | |
| ICON_MODE="NAME" | |
| read -p " Enter a system icon name (e.g., 'google-calendar', 'slack'): " ICON_DATA | |
| ;; | |
| S) | |
| ICON_MODE="SKIP" | |
| ;; | |
| *) | |
| ICON_MODE="AUTO" | |
| ;; | |
| esac | |
| echo "----------------------------------------------------" | |
| echo "β All information gathered. Proceeding with setup..." | |
| echo "----------------------------------------------------" | |
| # ============================================================================== | |
| # --- STAGE 2: PERFORM ACTIONS --- | |
| # ============================================================================== | |
| # --- 3. Set Up Variables --- | |
| APP_NAME_SANITIZED=$(echo "$APP_NAME" | tr -s ' ' '-' | tr -cd '[:alnum:]_-') | |
| PROFILE_NAME="ssb-$APP_NAME_SANITIZED" | |
| WM_CLASS="$APP_NAME_SANITIZED-SSB" | |
| FIREFOX_DIR="$HOME/.mozilla/firefox" | |
| PROFILE_DIR="$FIREFOX_DIR/$PROFILE_NAME" | |
| APPS_DIR="$HOME/.local/share/applications" | |
| ICONS_DIR="$HOME/.local/share/icons/hicolor/128x128/apps" | |
| # --- 4. Check for Existing Profile --- | |
| if [ -d "$PROFILE_DIR" ]; then | |
| echo "β Error: A profile named '$PROFILE_NAME' already exists." >&2 | |
| echo "To remove it, run 'firefox -P' from your terminal or visit 'about:profiles' in Firefox." >&2 | |
| exit 1 | |
| fi | |
| # --- 5. Create Profile, Preferences, and Directories --- | |
| mkdir -p "$APPS_DIR" "$ICONS_DIR" | |
| echo "βοΈ Creating new Firefox profile: $PROFILE_NAME..." | |
| firefox --headless -CreateProfile "$PROFILE_NAME $PROFILE_DIR" > /dev/null 2>&1 | |
| if [ ! -d "$PROFILE_DIR" ]; then | |
| echo "β Error: Failed to create profile directory." >&2 | |
| exit 1 | |
| fi | |
| echo "βοΈ Setting preferences to use system title bar..." | |
| cat <<EOF > "$PROFILE_DIR/user.js" | |
| // --- Preferences for SSB --- | |
| // 1. Force system title bar (set both for compatibility) | |
| user_pref("browser.tabs.drawInTitlebar", false); | |
| user_pref("browser.tabs.inTitlebar", 0); | |
| // 2. Enable userChrome.css customizations | |
| user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true); | |
| EOF | |
| echo "βοΈ Applying custom CSS for a slim, auto-hiding toolbar..." | |
| CHROME_DIR="$PROFILE_DIR/chrome" | |
| mkdir -p "$CHROME_DIR" | |
| # This CSS creates a slim tab bar that auto-hides along with the address bar. | |
| cat <<'EOF' > "$CHROME_DIR/userChrome.css" | |
| /* 1. Make the tab bar slim and compact */ | |
| #TabsToolbar { | |
| --tab-min-height: 28px !important; | |
| margin-bottom: -4px !important; /* Pulls the nav-bar up slightly */ | |
| } | |
| .tab-background { | |
| margin-block: 2px !important; | |
| } | |
| .tab-label-container { | |
| font-size: 0.9em; | |
| } | |
| /* 2. Auto-hide the entire navigator toolbox (tabs and URL bar) */ | |
| :root:not([customizing]) #navigator-toolbox:not(:hover):not(:focus-within) { | |
| max-height: 5px; /* Leaves a small sliver visible as a hint */ | |
| min-height: 0; | |
| opacity: 0.2; | |
| transition: all 0.2s ease-in-out; | |
| } | |
| /* 3. When hovered, expand the toolbox to its natural height */ | |
| :root:not([customizing]) #navigator-toolbox:hover, | |
| :root:not([customizing]) #navigator-toolbox:focus-within { | |
| max-height: 100px; /* Make this large enough to show everything */ | |
| opacity: 1; | |
| } | |
| EOF | |
| # --- 6. Process and Set Icon --- | |
| ICON_FILE_PATH="$ICONS_DIR/$PROFILE_NAME.png" | |
| ICON_NAME="$PROFILE_NAME" | |
| echo "βοΈ Processing icon choice..." | |
| case $ICON_MODE in | |
| URL) | |
| if curl -sL "$ICON_DATA" -o "$ICON_FILE_PATH"; then echo "β Icon downloaded successfully from URL."; else echo "β οΈ Warning: Could not download icon from URL. A generic web icon will be used."; ICON_NAME="web-browser"; fi ;; | |
| NAME) | |
| ICON_NAME="$ICON_DATA" | |
| echo "β Using system icon name '$ICON_NAME'." ;; | |
| SKIP) | |
| ICON_NAME="web-browser" | |
| echo "β Skipping icon, will use a generic icon." ;; | |
| AUTO) | |
| if curl -sL "https://www.google.com/s2/favicons?sz=128&domain_url=${APP_URL}" -o "$ICON_FILE_PATH"; then echo "β Icon auto-detected and downloaded successfully."; else echo "β οΈ Warning: Could not auto-detect icon. A generic web icon will be used."; ICON_NAME="web-browser"; fi ;; | |
| esac | |
| # --- 7. Create Desktop File --- | |
| echo "βοΈ Creating application shortcut (.desktop file)..." | |
| DESKTOP_FILE_PATH="$APPS_DIR/$PROFILE_NAME.desktop" | |
| cat <<EOF > "$DESKTOP_FILE_PATH" | |
| [Desktop Entry] | |
| Version=1.0 | |
| Type=Application | |
| Name=$APP_NAME | |
| Comment=Run $APP_NAME as a standalone web application | |
| Exec=firefox --name=$WM_CLASS --class=$WM_CLASS --no-remote -P "$PROFILE_NAME" "$APP_URL" | |
| Icon=$ICON_NAME | |
| Terminal=false | |
| StartupNotify=true | |
| Categories=Network;WebBrowser; | |
| StartupWMClass=$WM_CLASS | |
| EOF | |
| # --- 8. Finalize --- | |
| update-desktop-database -q "$APPS_DIR" | |
| echo "" | |
| echo "π All done! π" | |
| echo "The app '$APP_NAME' is now available in your application launcher." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment