> ## Documentation Index
> Fetch the complete documentation index at: https://docs.glassine.ink/llms.txt
> Use this file to discover all available pages before exploring further.

# Building from source

> The repository, the build script, the two flavors, and how this site is kept.

Glassine is a Swift package — SwiftUI for the chrome, AppKit for the editor — with no dependencies and no Xcode project. A shell script assembles the app. The source is at [github.com/a-libre/glassine](https://github.com/a-libre/glassine) under the MIT license.

## Build

You need Xcode (free, from the App Store) for its toolchain; the Xcode app itself never has to open.

```bash theme={null}
git clone https://github.com/a-libre/glassine.git
cd glassine
./build.sh --install     # compiles, copies Glassine.app to /Applications, opens it
```

| Command                 |                                                                            |
| ----------------------- | -------------------------------------------------------------------------- |
| `./build.sh`            | Build only, into `build/Glassine.app`                                      |
| `./build.sh --run`      | Build and open it from there, without installing                           |
| `./build.sh --install`  | Build, copy to `/Applications` (asking a running copy to quit first), open |
| `./build.sh --debug`    | A faster, unoptimised compile while you are changing things                |
| `./build.sh --appstore` | The sandboxed App Store flavor, locally                                    |

Edit anything under `Sources/Glassine/` and run `./build.sh --run`; incremental builds take a few seconds. Opening `Package.swift` in Xcode and pressing Run works for debugging, but the assembled app from `build.sh` is the one to use day to day — it has the icon and a stable identity for macOS permissions.

The minimum deployment target is macOS 14. It is developed on macOS 26 and 27 with Xcode 26.

## Layout

```
Sources/Glassine/
  App/        GlassineApp (scenes, menus, the key monitor), AppState, Settings, Theme
  Library/    Library (folder scanning and file operations), Document (autosave, renaming)
  Editor/     GlassineTextView (smooth caret, layout, typewriter, focus, motion),
              MarkdownStyler, StyleConfig, DateToken (the layout manager), TaskReorder
  UI/         ContentView, SidebarView, GalleryView, DailyTimelineView, ReviewView,
              SettingsView, ShortcutSheet, Overlays, GlassBackground
  Support/    Distribution (sandbox / App Store differences), DailyNotes, Shelf,
              ScreenshotMode (the app photographs itself for the store), small extensions
Resources/    Info.plist, the icon (make_icon.py draws it), entitlements per flavor, the wordmark
docs/
  appstore/   The store listing, a showcase library, and the script that takes the screenshots
  screenshots/ The pictures the README uses
  site/       This site
site/         glassine.ink, the one-page front door (static HTML on Vercel; vercel.json holds the redirects)
build.sh      Assembles and signs Glassine.app (--appstore for the sandboxed flavor)
release.sh    Notarized .dmg for direct download
appstore.sh   Signed .pkg for the Mac App Store
```

## Two flavors

`./build.sh --appstore` compiles with `APPSTORE` set, which turns on the App Sandbox, gives the app its own iCloud container instead of direct access to iCloud Drive, remembers chosen folders with security-scoped bookmarks, and leaves out the GitHub update check. `Support/Distribution.swift` is where the differences are decided at run time. [RELEASING.md](https://github.com/a-libre/glassine/blob/main/RELEASING.md) in the repository has the whole pipeline for both — certificates, notarization, the store package.

## Debugging

Help → Copy Debug Info (⌘⌥⇧D) snapshots the caret's geometry, the text view's frame and insets, and every setting, ready to paste into an issue.

The app can also photograph itself: launched with `-glassine.shoot name.png` and a few companion arguments (see `Support/ScreenshotMode.swift`), it opens at a fixed size with the settings, view and caret position you name, waits for layout, asks the window server for a picture of its own window — that window only, so nothing needs the Screen Recording permission — and quits. `-glassine.shootCapture 1` asks for the fuller composite with the backdrop beneath, which the store pictures use; macOS counts that as screen recording and says so with a notice. `docs/appstore/screenshots.sh` uses this to take the store pictures, and it is how visual changes are checked without anyone sitting at the Mac.

## The front door

[glassine.ink](https://glassine.ink) is one static page in `site/`, served by Vercel from the same repository; a push to `main` publishes it too. `site/vercel.json` carries the redirects: `glassinewriter.com` and `www.` to `glassine.ink`, and short paths like `/docs`, `/privacy`, `/changelog`, `/support` and `/download` to where those live. Nothing on it changes often — everything that does lives here, in the manual.

## This site

This site, [docs.glassine.ink](https://docs.glassine.ink), lives in `docs/site` in the same repository and is built by [Mintlify](https://mintlify.com): `docs.json` is the navigation and `*.mdx` are the pages. A push to `main` publishes it within a minute or two. To preview locally:

```bash theme={null}
npm i -g mint
cd docs/site
mint dev
```

`mint validate` and `mint broken-links` check a change before it goes up.

The rule for keeping it current is simple: a change that a person using Glassine would notice — a new key, a setting, a behaviour, a small delight — updates the page it belongs to and adds a line to the [changelog](/about/changelog) in the same commit.
