Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
186 commits
Select commit Hold shift + click to select a range
7a61b82
feat(dev-tools): add rotate-sessions developer tool
Just-Insane Mar 31, 2026
d5546da
chore: add changeset for devtool-rotate-sessions
Just-Insane Mar 31, 2026
fe1018c
fix(dev-tools): address review feedback for rotate-sessions
Just-Insane Apr 15, 2026
db6f398
chore: remove accidentally committed scratch files
Just-Insane Apr 15, 2026
b7d74ef
fix(dev-tools): add error handling for prepareToEncrypt
Just-Insane Apr 15, 2026
e2ebd4c
chore: fix lint and format issues
Just-Insane Apr 15, 2026
9fe62d6
docs(changeset): clarify Megolm session rotation description
Just-Insane Apr 15, 2026
95a802e
feat(flags): inject client config from GH environment variables at build
Just-Insane Mar 29, 2026
291cecd
feat(flags): add typed experiment bucketing helper with rollout perce…
Just-Insane Mar 29, 2026
de7e980
feat(devtools): add Experiments panel to developer tools settings
Just-Insane Mar 29, 2026
e967bd3
test(flags): cover experiment bucketing and add changeset
Just-Insane Mar 29, 2026
1911cae
fix(devtools): add focusId to ExperimentsPanel SettingTile
Just-Insane Apr 8, 2026
f33284d
fix(security): block prototype-polluting keys in deepMerge
Just-Insane Apr 12, 2026
ad2ef39
feat(bookmarks): add message bookmarks (MSC4438)
Just-Insane Apr 6, 2026
a64e8c3
test(bookmarks): add unit tests for MSC4438 bookmark domain and repos…
Just-Insane Apr 6, 2026
9e5deec
chore: add changeset for message-bookmarks
Just-Insane Apr 6, 2026
bc9d597
fix(bookmarks): add missing focusId to MSC4438 settings SettingTile
Just-Insane Apr 8, 2026
297ffa8
fix(bookmarks): soft-delete item before updating index in removeBookmark
Just-Insane Apr 9, 2026
fed3554
fix(bookmarks): wire useInitBookmarks and fix orphan tombstoning
Just-Insane Apr 12, 2026
914019a
fix(bookmarks): strip deleted flag on re-add to guarantee re-activation
Just-Insane Apr 12, 2026
459f3a1
feat(bookmarks): show Recently Removed section with Restore button
Just-Insane Apr 12, 2026
5b66126
test(bookmarks): format repository tests for prettier compliance
Just-Insane Apr 13, 2026
5ce7093
fix(bookmarks): react to item-level account data events and fix remov…
Just-Insane Apr 13, 2026
faa490f
fix(bookmarks): add Fragment key, guard missing eventId, fix removeBo…
Just-Insane Apr 15, 2026
148d9eb
fix(nav): check DM membership before space parents in useRoomNavigate
Just-Insane Apr 15, 2026
04a72cd
fix(timeline): restore useLayoutEffect auto-scroll, fix new-message s…
Just-Insane Apr 16, 2026
14d4745
fix(timeline): restore upstream scroll pattern for new messages
Just-Insane Apr 16, 2026
b6b0b7b
fix(timeline): align scrollToBottom with upstream, fix eventId race
Just-Insane Apr 17, 2026
c6fd535
fix(bookmarks): remove unrelated branch spillover
Just-Insane Apr 19, 2026
1fd8b9c
chore(bookmarks): fix branch validation issues
Just-Insane Apr 19, 2026
4020c08
feat(polls): implement MSC3381 polls with creator dialog and timeline…
Just-Insane Apr 6, 2026
ba66bbb
chore: add changeset for feat-polls
Just-Insane Apr 6, 2026
3e2af04
feat(polls): expose max_selections in poll creator dialog
Just-Insane Apr 9, 2026
8ce1d2b
test(polls): unit-test pure functions; export extractPollData/compute…
Just-Insane Apr 11, 2026
e4b2fc3
fix: auto-format poll test imports for prettier compliance
Just-Insane Apr 12, 2026
7bcc3e2
fix: remove unused params from mock Room callbacks
Just-Insane Apr 12, 2026
37a5bac
fix: address PR #589 review comments
Just-Insane Apr 13, 2026
47afe2b
fix(polls): handle encrypted poll events in timeline filter
Just-Insane Apr 15, 2026
62f04a6
fix(polls): strip invalid vote selections instead of discarding entir…
Just-Insane Apr 15, 2026
50a956b
feat(presence): add presence badges to sidebar and fix sliding sync p…
Just-Insane Mar 31, 2026
01333f0
chore: add changeset for presence-sidebar-badges
Just-Insane Mar 31, 2026
edb7b27
fix(presence): skip REST presence fetch when userId is empty string
Just-Insane Apr 9, 2026
afdead0
test(presence): add useUserPresence unit tests
Just-Insane Apr 11, 2026
d0e759d
feat(presence): add presenceMode setting and Discord-style status picker
Just-Insane Apr 11, 2026
fb4c8f8
feat(presence): Discord-style presence picker with Idle, DND, and Inv…
Just-Insane Apr 11, 2026
9b2f321
fix(presence): resolve missing deps and stabilize presence hook tests
Just-Insane Apr 12, 2026
f55e0f1
fix(presence): address review feedback for presence sidebar badges
Just-Insane Apr 15, 2026
c2b9a96
feat(presence): add presence badges to sidebar and fix sliding sync p…
Just-Insane Mar 31, 2026
963824d
fix(presence): skip REST presence fetch when userId is empty string
Just-Insane Apr 9, 2026
1492db2
test(presence): add useUserPresence unit tests
Just-Insane Apr 11, 2026
bb19ff1
feat(presence): add presenceMode setting and Discord-style status picker
Just-Insane Apr 11, 2026
21a6d5d
feat(presence): Discord-style presence picker with Idle, DND, and Inv…
Just-Insane Apr 11, 2026
3084d13
feat(presence): auto-idle after inactivity timeout
Just-Insane Apr 12, 2026
9dacfdc
chore: add changeset for presence-auto-idle
Just-Insane Apr 12, 2026
be4bec9
fix(presence): restore missing experiment config helpers and clean pr…
Just-Insane Apr 12, 2026
39519a9
fix(presence): address review feedback for presence-auto-idle
Just-Insane Apr 15, 2026
181c075
fix(presence): 5min default, wire visibility reset, add tests
Just-Insane Apr 15, 2026
d190264
refactor: align presence-auto-idle with sw-push-session-recovery
Just-Insane Apr 15, 2026
4d04c0b
style: fix lint errors from merge
Just-Insane Apr 15, 2026
f413a43
fix(presence): address review feedback
Just-Insane Apr 15, 2026
fe4c6a3
chore: fix lint and format issues
Just-Insane Apr 15, 2026
83bc6cc
fix(presence): retry setPresence on failure for app resume reliability
Just-Insane Apr 16, 2026
6dd594c
fix(presence): normalize dnd state handling
Just-Insane Apr 19, 2026
3d2d575
fix(presence): harden desktop auto-idle detection
Just-Insane Apr 19, 2026
fdbac9d
feat(room-nav): show topic/last-message preview for space and home rooms
Just-Insane Apr 12, 2026
c7783dc
fix(sliding-sync): increase LIST_TIMELINE_LIMIT to 5 for message prev…
Just-Insane Apr 12, 2026
1ee6322
chore: add changeset for room-message-preview
Just-Insane Apr 12, 2026
7245aa1
feat(dm-list): show latest message preview below room name
Just-Insane Apr 12, 2026
2fa3342
chore: add changeset for dm message preview
Just-Insane Apr 12, 2026
b811e45
feat(dm-list): add toggle to hide DM message preview
Just-Insane Apr 12, 2026
1909bd0
refactor(sliding-sync): gate listTimelineLimit behind message preview…
Just-Insane Apr 14, 2026
5abd1f8
fix: use || instead of ?? for DM preview fallback chain The nullish …
Just-Insane Apr 14, 2026
4ce48da
fix(room-nav): address review feedback for message preview
Just-Insane Apr 15, 2026
36065bb
test(room-nav): add useRoomLastMessage unit tests (28 tests)
Just-Insane Apr 15, 2026
6cd97b4
fix(room-nav): use effective event type for decrypted message preview…
Just-Insane Apr 15, 2026
4383c4b
chore: fix lint and format issues
Just-Insane Apr 15, 2026
a852c75
docs: clarify that listTimelineLimit scales with message preview setting
Just-Insane Apr 15, 2026
ef672d1
fix(preview): close decryption race in useRoomLastMessage
Just-Insane Apr 16, 2026
ed0312e
fix(preview): poll/location preview, mxid localpart fallback
Just-Insane Apr 16, 2026
eac4c42
fix(timeline): restore useLayoutEffect auto-scroll, fix new-message s…
Just-Insane Apr 16, 2026
e70e4ac
fix(timeline): restore upstream scroll pattern for new messages
Just-Insane Apr 16, 2026
c5af048
fix(timeline): align scrollToBottom with upstream, fix eventId race
Just-Insane Apr 17, 2026
2809ea7
perf(sidebar): debounce room preview and DM sort updates
Just-Insane Apr 18, 2026
40f7382
fix(preview): resolve display names in room previews
Just-Insane Apr 18, 2026
6270b40
fix(preview): remove timeline spillover
Just-Insane Apr 19, 2026
199efeb
fix(hooks): handle unhandled rejections in useAsyncCallback
Just-Insane Mar 31, 2026
c08fdb1
chore: add changeset for async-callback-rejections
Just-Insane Mar 31, 2026
54be472
docs(changeset): accurately describe unhandled-rejection suppression …
Just-Insane Apr 15, 2026
4906b10
fix(notifications): skip in-app notification for active room
Just-Insane Apr 17, 2026
38a731c
fix(notifications): pass room and userId context to reaction notifica…
Just-Insane Apr 12, 2026
58ec144
fix(badge): only clear app badge when foregrounded
Just-Insane Apr 16, 2026
be9a5a4
fix(notifications): open joined rooms at live timeline on notificatio…
Just-Insane Apr 13, 2026
17b66f1
fix(notifications): prefer live timeline before event-scoped jump
Just-Insane Apr 13, 2026
1aec2a8
fix(notifications): defer event-scoped jump until event appears in li…
Just-Insane Apr 13, 2026
b9def38
fix(notifications): improve notification jump reliability
Just-Insane Apr 18, 2026
5095edd
fix(notifications): guarantee jump timeout fallback
Just-Insane Apr 19, 2026
ba3f2fa
test(notifications): align jumper room mock with room utils
Just-Insane Apr 19, 2026
126bb3d
test(notifications): use current jotai hydrate api
Just-Insane Apr 19, 2026
62d712c
test(notifications): initialize jumper atoms via jotai store
Just-Insane Apr 19, 2026
fe6e028
fix(notifications): avoid jumper ref lint error
Just-Insane Apr 19, 2026
ee3fd3e
fix(notifications): normalize DM room names
Just-Insane Apr 18, 2026
775b177
fix(sw): reuse preloaded session in handleMinimalPushPayload
Just-Insane Apr 15, 2026
62ebfb1
fix(sw): improve push notification reliability and encrypted room han…
Just-Insane Apr 15, 2026
34b40ed
fix(sw): add media and notification diagnostics
Just-Insane Apr 19, 2026
c37c9d7
fix(sw): increase session TTL to 24h and add requestSessionWithTimeou…
Just-Insane Apr 11, 2026
be49cde
fix(sw): reset heartbeat backoff on foreground sync; warm preloadedSe…
Just-Insane Apr 11, 2026
bc73097
fix(notifications): restore background visibility sync
Just-Insane Apr 18, 2026
7ebd31e
fix(sw): recover session sync without controller
Just-Insane Apr 19, 2026
3fdf316
fix: kick sliding sync on foreground return
Just-Insane Apr 15, 2026
c65be5c
fix(config): enable SW session sync phases for reliable mobile notifi…
Just-Insane Apr 15, 2026
77547d0
fix(timeline): stabilize bottom pin and unread fallback
Just-Insane Apr 19, 2026
bbaa4bc
fix(timeline): align initial room-fill thresholds
Just-Insane Apr 19, 2026
386f973
fix(timeline): align reset relinking with upstream
Just-Insane Apr 19, 2026
4265ae4
feat(cache): unregister service workers on Clear Cache
Just-Insane Apr 16, 2026
f6b29e6
fix(nav): check DM membership before space parents in useRoomNavigate
Just-Insane Apr 15, 2026
d4447c8
Change GitHub owner from 'SableClient' to 'Just-Insane'
Just-Insane Mar 21, 2026
01a699e
Change default custom domain for Worker
Just-Insane Mar 21, 2026
a624041
Change default custom domain in variables.tf
Just-Insane Mar 21, 2026
dfe1450
Change default custom domain to dev.cloudhub.social
Just-Insane Mar 21, 2026
a495286
chore: ignore .vscode/launch.json
Just-Insane Mar 25, 2026
3e13abb
ci: build latest Docker image from integration branch too
Just-Insane Mar 25, 2026
e411e59
ci: add Sentry env vars to Docker image build step
Just-Insane Mar 25, 2026
4db08b5
ci: tag integration branch Docker image as 'integration'
Just-Insane Mar 27, 2026
8dfe666
feat: add pre-push git hook for quality checks
Just-Insane Mar 28, 2026
a56dd10
ci(docker): load env-specific client config overrides
Just-Insane Mar 28, 2026
e3f3939
ci: integration uses preview env, dev uses production env
Just-Insane Mar 29, 2026
827d29d
ci(workflows): trigger app deploys on config.json changes
Just-Insane Mar 29, 2026
a6643df
chore: codespace devcontainer config
Just-Insane Mar 29, 2026
928663c
Update image
Just-Insane Mar 29, 2026
9e8735c
update startup script
Just-Insane Mar 29, 2026
b9587fa
Update setup-signing script
Just-Insane Mar 29, 2026
ed3b571
Updates for ssh
Just-Insane Mar 29, 2026
b27232c
More script fixes
Just-Insane Mar 29, 2026
cd187d1
more fixes
Just-Insane Mar 29, 2026
1eb238b
updates
Just-Insane Mar 29, 2026
e9e03f6
add/setup extensions
Just-Insane Mar 29, 2026
8491583
chore(config): add Copilot workspace instructions
Just-Insane Mar 29, 2026
b34be8f
chore(config): remove devcontainer (setup didn't work out)
Just-Insane Mar 29, 2026
4416696
Revise GitHub Copilot workspace instructions
Just-Insane Mar 29, 2026
eabb989
Update branching instructions for syncing with upstream
Just-Insane Mar 29, 2026
ba8b222
Revise instructions for clarity and consistency
Just-Insane Mar 30, 2026
dc5b5a8
Move `copilot-instructions.md` to correct location
Just-Insane Mar 30, 2026
714800b
Clarify branch creation and PR instructions
Just-Insane Mar 30, 2026
3849d44
Docs have this location too...
Just-Insane Mar 30, 2026
598b60d
chore(config): split copilot-instructions into scoped instruction fil…
Just-Insane Mar 31, 2026
8cdbee1
Update git instructions in AGENTS.md
Just-Insane Mar 31, 2026
c545a48
Update git commands
Just-Insane Mar 31, 2026
dfe6800
chore(codespace): add devcontainer for iPad browser + SSH signing
Just-Insane Apr 6, 2026
2633396
chore(codespace): add Fira Code font + ligatures
Just-Insane Apr 6, 2026
debac1b
chore(codespace): split onCreate/postCreate for prebuild caching
Just-Insane Apr 6, 2026
3bfa86e
chore(codespace): fix image tag, install OMZ+P10k, wire dotfiles bare…
Just-Insane Apr 6, 2026
06a3e50
fix(codespace): suppress corepack download prompt, source nvm in onCr…
Just-Insane Apr 6, 2026
cc17868
fix(codespace): chown pnpm store volume before writing
Just-Insane Apr 6, 2026
671fb1e
chore(devcontainer): add tmux, fix terminal font, add GitHub MCP server
Just-Insane Apr 6, 2026
e62e9f7
fix(devcontainer): use browser-safe font and compatible p10k glyphs f…
Just-Insane Apr 6, 2026
3a44ec6
fix(devcontainer): use Menlo as terminal font for iOS compatibility
Just-Insane Apr 6, 2026
e81e4e5
update devcontainer settings
Just-Insane Apr 7, 2026
f3f8cfd
fix(devcontainer): restore missing fontFamily settings
Just-Insane Apr 7, 2026
27266b3
Update fontfamily
Just-Insane Apr 7, 2026
47f2783
chore(devcontainer): sync extensions list with installed extensions
Just-Insane Apr 7, 2026
5e2af59
Update container config
Just-Insane Apr 7, 2026
ffcc16d
fix(devcontainer): load signing key into ssh-agent in postCreate
Just-Insane Apr 7, 2026
c94ce66
feat(devcontainer): add SSH_AUTH_KEY secret support for server access
Just-Insane Apr 7, 2026
41dea18
fix(devcontainer): disable extension MCP auto-discovery, fix p10k sed…
Just-Insane Apr 7, 2026
53b77a8
fix(devcontainer): enable shell integration for Copilot Chat terminal
Just-Insane Apr 7, 2026
5538e32
chore(devcontainer): switch dotfiles branch to codespaces
Just-Insane Apr 8, 2026
1ae3344
chore(prompts): add rebuild integration and review upstream PRs prompts
Just-Insane Apr 15, 2026
beb856d
fix(notifications): add registration.active fallback for SW message r…
Just-Insane Apr 21, 2026
53a5a33
fix(timeline): remove duplicate MIN_INITIAL_SCROLL_ROOM_PX declaration
Just-Insane Apr 21, 2026
4f7638d
fix(timeline): restore missing refs and roomScrollCache utility
Just-Insane Apr 21, 2026
092567c
fix(lint): resolve all ESLint errors across integration
Just-Insane Apr 21, 2026
c85bae7
feat(timeline): configurable message grouping threshold
Just-Insane Apr 22, 2026
b774894
fix(sw): defer skipWaiting to user-confirmed update prompt
Just-Insane Apr 22, 2026
8f6e44a
Merge fix/sw-update-skipwaiting into integration
Just-Insane Apr 22, 2026
8475092
fix(room-nav): use stable room ID keys in virtualized room lists
Just-Insane Apr 22, 2026
29486bb
fix(presence): add heartbeat to win back online state on multi-device
Just-Insane Apr 22, 2026
4c7b344
fix(notifications): re-register pusher on mount and catch togglePushe…
Just-Insane Apr 22, 2026
55bbb7e
fix(notifications): clear badge on foreground when highlights already…
Just-Insane Apr 22, 2026
921c816
fix(notifications): restore unread fallback paths for non-DM rooms
Just-Insane Apr 22, 2026
ec5cf6e
fix(sw): remove 24h session TTL and guard event.data.json()
Just-Insane Apr 24, 2026
e38f99a
fix(sw): require focused+visible to suppress push on iOS
Just-Insane Apr 24, 2026
b796b13
fix(timeline): restore visible timeline when loadEventTimeline fails
Just-Insane Apr 24, 2026
bad4c2d
fix(SyncStatus): only show Connecting... on reconnect, not initial load
Just-Insane Apr 24, 2026
c9aeec9
fix(sw): guard decrypt-relay suppression with appFocused check
Just-Insane Apr 26, 2026
0625646
revert(SyncStatus): restore upstream connecting banner condition
Just-Insane Apr 26, 2026
78dd5fb
chore(feat/developer-tools): merge upstream dev (MSC4140 graceful fai…
Just-Insane May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/async-callback-rejections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: patch
---

Suppress "Uncaught (in promise)" console noise for fire-and-forget `useAsyncCallback` call sites; errors are still surfaced to callers that await the returned promise and captured in `AsyncState`
5 changes: 5 additions & 0 deletions .changeset/devtool-rotate-sessions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: patch
---

Add developer tool to force-rotate outbound Megolm encryption sessions per room, useful for testing key rotation and bridge session recovery
5 changes: 5 additions & 0 deletions .changeset/feat-dm-message-preview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

feat(dm-list): show last-message preview below DM room name
5 changes: 5 additions & 0 deletions .changeset/feat-polls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

Add MSC3381 polls: create, vote on, and end polls directly in rooms (opt-in via `features.polls` in config.json).
5 changes: 5 additions & 0 deletions .changeset/feature-flag-env-vars.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

Add build-time client config overrides via environment variables, with typed deterministic experiment bucketing helpers for progressive feature rollout and A/B testing.
5 changes: 5 additions & 0 deletions .changeset/message-bookmarks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

Add message bookmarks (MSC4438). Users can bookmark messages for easy retrieval via a new Bookmarks section in the home sidebar. Gated by an operator `config.json` experiment flag (`experiments.messageBookmarks`) and a per-user experimental settings toggle.
5 changes: 5 additions & 0 deletions .changeset/presence-auto-idle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

feat(presence): add auto-idle presence after configurable inactivity timeout with Discord-style status picker
5 changes: 5 additions & 0 deletions .changeset/presence-sidebar-badges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: patch
---

Add presence status badges to sidebar DM list and account switcher
5 changes: 5 additions & 0 deletions .changeset/reaction-notification-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: patch
---

Fix reaction notifications not being delivered by passing room and user context to the notification event filter
5 changes: 5 additions & 0 deletions .changeset/room-message-preview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

feat(room-nav): show topic and last-message preview for rooms in the sidebar, fetching enough timeline events to handle reactions and edits correctly
152 changes: 152 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Codespace configuration — lives on personal/config (not ephemeral dev/feat branches).
// This file intentionally targets browser-based use on iPad.
{
"name": "Sable",
// Using base + node feature instead of javascript-node:<tag> to avoid
// tag availability issues on newer Node versions.
"image": "mcr.microsoft.com/devcontainers/base:bookworm",

"features": {
"ghcr.io/devcontainers/features/node:1": { "version": "24" },
// Keep git up-to-date for SSH signing support (git ≥ 2.34).
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},

// ── Codespace user secrets ──────────────────────────────────────────────────
// Configure these at: github.com/settings/codespaces > Secrets
//
// GIT_SIGNING_KEY — passphrase-free SSH private key (ed25519 recommended).
// Add the matching public key to your GitHub account as a
// "signing key": github.com/settings/keys
// postCreate.sh will wire up git automatically if set.
//
// SSH_AUTH_KEY — passphrase-free SSH private key (ed25519 recommended).
// Add the matching public key to ~/.ssh/authorized_keys on
// any server you want to SSH into from the Codespace.
//
// GIT_USER_NAME — e.g. "Evie"
// GIT_USER_EMAIL — e.g. "evie@gauthier.id"
// ───────────────────────────────────────────────────────────────────────────

"remoteEnv": {
// Pin the pnpm store to a known path so the volume mount works across rebuilds.
"PNPM_STORE_DIR": "/home/vscode/.pnpm-store"
},

"customizations": {
"vscode": {
"settings": {
// ── Layout — tuned for iPad browser (vscode.dev / Codespaces web) ─────
// Move the activity bar to the top so it isn't hidden by the iOS Safari
// toolbar or the browser's combined title/status bar.
"workbench.activityBar.location": "top",
// Use a menu for the layout control — fewer tiny hit targets on touch.
"workbench.layoutControl.type": "menu",
// Place the panel (Terminal, Problems, Copilot Chat history) on the
// right so it doesn't fight with the keyboard on small screens.
"workbench.panel.defaultLocation": "right",
// Keep editor tabs visible and wrap them so none are hidden off-screen.
"workbench.editor.showTabs": "multiple",
"workbench.editor.wrapTabs": true,
// Disable minimap — saves horizontal space, improves touch accuracy.
"editor.minimap.enabled": false,
"editor.scrollBeyondLastLine": false,
// Larger default fonts for retina/HiDPI iPad displays.
// Fira Code is loaded as a web font by the tonsky.font-fira-code extension.
// This works for the Monaco *editor* (HTML/CSS rendered), but xterm.js uses
// canvas drawing — it does NOT reliably inherit CSS @font-face on iOS Safari.
// MesloLGS NF / Monaco / Meslo are not iOS system fonts either.
// → Editor: Fira Code via extension is fine.
// → Terminal: use Menlo only (ships with iOS since iOS 7, always available).
"editor.fontSize": 14,
"editor.fontFamily": "'MesloLGS NF', 'Fira Code', Menlo, 'Courier New', monospace",
"editor.fontLigatures": true,
"terminal.integrated.fontSize": 14,
"terminal.integrated.fontFamily": "Menlo, 'Courier New', monospace",
"terminal.integrated.fontLigatures.enabled": false,
"terminal.integrated.gpuAcceleration": "off",

// Use zsh (installed in onCreate) as the default terminal shell.
// Explicit profile with -l (login shell) ensures nvm / PATH additions
// from the devcontainer node feature are loaded inside the terminal.
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"zsh": { "path": "/bin/zsh", "args": ["-l"] }
},

// Shell integration MUST be enabled for Copilot Chat to run terminal
// commands. We set it explicitly because Powerlevel10k instant prompt
// can fire before VS Code injects its integration script and suppress
// the markers — postCreate.sh patches .zshrc to guard against this.
"terminal.integrated.shellIntegration.enabled": true,

// ── Git signing ───────────────────────────────────────────────────────
// postCreate.sh configures gpg.format and user.signingkey if
// GIT_SIGNING_KEY secret is present. This just keeps VS Code's git
// UI in sync.
"git.enableCommitSigning": true,
"git.confirmSync": false,

// ── Copilot Chat ──────────────────────────────────────────────────────
// Always show follow-ups and keep chat history accessible.
"github.copilot.chat.followUps": "always",
// Disable auto-discovery of extension-provided MCP servers (e.g. the
// io.github.github/github-mcp-server registered by vscode-pull-request-github).
// Our explicit HTTP server in .vscode/mcp.json is unaffected and handles all
// GitHub MCP calls without requiring a token prompt.
"chat.mcp.discovery.enabled": false
},
"extensions": [
// ── Copilot ───────────────────────────────────────────────────────────
"GitHub.copilot",
"GitHub.copilot-chat",
"GitHub.vscode-pull-request-github",
// ── Font (web font — required for terminal in browser/iPad) ───────────
"tonsky.font-fira-code",
// ── Theme ─────────────────────────────────────────────────────────────
"GitHub.github-vscode-theme",
// ── Formatting & linting ──────────────────────────────────────────────
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"streetsidesoftware.code-spell-checker",
"davidanson.vscode-markdownlint",
// ── Testing ───────────────────────────────────────────────────────────
"vitest.explorer",
// ── TypeScript / React ────────────────────────────────────────────────
"bradlc.vscode-tailwindcss",
"styled-components.vscode-styled-components",
"dsznajder.es7-react-js-snippets",
"formulahendry.auto-rename-tag",
"wix.vscode-import-cost",
// ── Utilities ─────────────────────────────────────────────────────────
"christian-kohler.path-intellisense",
"usernamehw.errorlens",
"gruntfuggly.todo-tree",
"wayou.vscode-todo-highlight",
"webpro.vscode-knip",
"lokalise.i18n-ally",
// ── Infrastructure ────────────────────────────────────────────────────
"hashicorp.terraform",
"zamerick.vscode-caddyfile-syntax"
]
}
},

// ── Port forwarding ─────────────────────────────────────────────────────────
"forwardPorts": [5173, 4173],
"portsAttributes": {
"5173": { "label": "Vite dev", "onAutoForward": "notify" },
"4173": { "label": "Vite preview", "onAutoForward": "notify" }
},

// ── Persistence ─────────────────────────────────────────────────────────────
// Named volume keeps the pnpm content-addressable store across rebuilds.
// Combined with the PNPM_STORE_DIR env var above so postCreate can also
// point pnpm at the same path.
"mounts": ["source=sable-pnpm-store,target=/home/vscode/.pnpm-store,type=volume"],

"postCreateCommand": "bash .devcontainer/postCreate.sh",
"onCreateCommand": "bash .devcontainer/onCreate.sh",
"remoteUser": "vscode"
}
60 changes: 60 additions & 0 deletions .devcontainer/onCreate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/bash
# onCreate.sh — runs during prebuild AND on first Codespace creation.
# No user secrets are available here — keep this purely about dependencies.
# Everything here is cached in the prebuild snapshot.
set -euo pipefail

# ── Ensure the node feature's PATH additions are active ──────────────────────
# The devcontainers node feature installs via nvm; source it so `node`/`pnpm`
# resolve correctly even in non-login, non-interactive shells.
export NVM_DIR="${NVM_DIR:-/usr/local/share/nvm}"
# shellcheck source=/dev/null
[ -s "${NVM_DIR}/nvm.sh" ] && source "${NVM_DIR}/nvm.sh" --no-use
# Activate the version pinned in .nvmrc / package.json engines.
nvm use 24 2>/dev/null || nvm use node

# ── Fix named-volume ownership ────────────────────────────────────────────────
# Docker mounts named volumes as root; fix ownership so the vscode user can write.
if [ -d "${PNPM_STORE_DIR:-}" ]; then
sudo chown -R "$(id -u):$(id -g)" "${PNPM_STORE_DIR}"
fi

# ── pnpm ──────────────────────────────────────────────────────────────────────
# Suppress corepack's interactive download-confirmation prompt in CI/prebuild.
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0

# Enable corepack so the exact pnpm version from package.json#packageManager is used.
corepack enable

# Point pnpm at the persistent named-volume store so packages survive rebuilds.
if [ -n "${PNPM_STORE_DIR:-}" ]; then
pnpm config set store-dir "${PNPM_STORE_DIR}"
fi

pnpm install

# ── Zsh + Oh My Zsh + Powerlevel10k ──────────────────────────────────────────
# Install these during prebuild so the first Codespace start is fast.
# The dotfiles checkout in postCreate.sh will provide .zshrc / .p10k.zsh.

# Install zsh and tmux if not already present (base:bookworm ships zsh, but be safe).
if ! command -v zsh &>/dev/null || ! command -v tmux &>/dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq zsh tmux
fi

# Install Oh My Zsh non-interactively (KEEP_ZSHRC=yes preserves any existing .zshrc).
if [ ! -d "${HOME}/.oh-my-zsh" ]; then
KEEP_ZSHRC=yes CHSH=no RUNZSH=no \
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
fi

# Install Powerlevel10k as an OMZ custom theme.
P10K_DIR="${ZSH_CUSTOM:-${HOME}/.oh-my-zsh/custom}/themes/powerlevel10k"
if [ ! -d "${P10K_DIR}" ]; then
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "${P10K_DIR}"
fi

# Make zsh the default shell for this user.
sudo chsh -s "$(command -v zsh)" "$(whoami)"

echo "✓ onCreate complete"
Loading
Loading