Skip to content

Instantly share code, notes, and snippets.

@SavageCore
Last active February 23, 2026 17:38
Show Gist options
  • Select an option

  • Save SavageCore/3b6a0f7dde7301604c2791b3bfaaef58 to your computer and use it in GitHub Desktop.

Select an option

Save SavageCore/3b6a0f7dde7301604c2791b3bfaaef58 to your computer and use it in GitHub Desktop.

Messenger "PWA" for KDE Plasma

With Meta retiring messenger.com and forcing redirects to facebook.com/messages, Electron wrappers like Caprine are breaking.

Here is how to create a standalone, native-feeling Messenger app using Brave on KDE Plasma.

Step 1: Create the Standalone Shortcut

Brave's GUI often obeys Facebook's web manifest, which prevents creating a clean windowed shortcut for specific sub-pages. We bypass this by manually creating a .desktop file using the --app= flag.

cat << 'EOF' > ~/.local/share/applications/brave-messenger.desktop
[Desktop Entry]
Name=Messenger
Exec=brave-browser --app=https://www.facebook.com/messages
Icon=messenger-pwa
Type=Application
Terminal=false
Categories=Network;InstantMessaging;
StartupWMClass=brave-www.facebook.com__messages-Default
EOF

Step 2: Apply Official Branding & Fix Wayland Icons

By default, the shortcut uses the generic browser icon, and KWin (KDE's Wayland compositor) may fail to associate the window, resulting in a generic Wayland logo on the taskbar and title bar.

Run the following block to download the official icon, apply it, and map the correct StartupWMClass.

# Download the Messenger SVG icon from selfhst/icons into your local user icons directory
mkdir -p ~/.local/share/icons/hicolor/scalable/apps/
curl -L -o ~/.local/share/icons/hicolor/scalable/apps/messenger-pwa.svg https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/facebook-messenger.svg

# Refresh KDE Plasma's application cache to apply the changes immediately
kbuildsycoca6

Note: You may need to log out and back into your Plasma session for KWin to apply the updated icon to the window title bar.

Step 3: Hide the Facebook UI (Optional but Recommended)

Because this PWA points to the main Facebook domain, the top navigation bar will still be visible. To make it look like a dedicated app, use a CSS extension like Stylus to inject this snippet (thanks to bankjaneo's Caprine fork for the fix!):

@-moz-document url-prefix("https://www.facebook.com/messages")
:root {
  --selected-conversation-background: linear-gradient(
    hsla(209deg 110% 45% / 90%),
    hsla(209deg 110% 42% / 90%)
  );
  --selected-conversation-background-inactive: #d2d2d2;
  --black: #000;
}

html {
  overflow: hidden;
}

/* Add OS-specific fonts */
body {
  font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
    Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji",
    "Segoe UI Emoji", "Segoe UI Symbol" !important;
  text-rendering: optimizelegibility !important;
  font-feature-settings: "liga", "clig", "kern";
}

/* View label above conversation list margin */
.os-darwin [role="navigation"] .x1heor9g.x1qlqyl8.x1pd3egz.x1a2a7pz {
  margin-left: 60px;
}

/* Hide footer at login view */
._210n {
  display: none;
}

/* Don't show outline on clickable elements & input fields */
*[role="button"],
*[type="text"],
*[type="password"] {
  outline: none !important;
}

[role="navigation"] a {
  cursor: default !important;
}

/* Remove top Facebook cookie banner */
.fbPageBanner {
  display: none !important;
}

/* Hide Facebook top navigation bar (not present on messenger.com) */
[role="banner"] {
  display: none !important;
}

/* Remove top offset and card spacing reserved for Facebook navbar and layout */
:root,
.__fb-light-mode,
.__fb-dark-mode {
  --header-height: 0 !important;
  --messenger-card-spacing: 0 !important;
}

/* Add card-style margins and gaps around the messenger layout (matching messenger.com spacing) */
div:has(> [role="navigation"][aria-label="Thread list"]) {
  padding: 16px !important;
  box-sizing: border-box !important;
  gap: 16px !important;
}

/* Add gap between chat area and right sidebar */
[role="main"] > div > div > div {
  gap: 16px !important;
}

/* Round the conversation list container to match the chat container */
[role="navigation"][aria-label="Thread list"] {
  border-radius: 8px !important;
  overflow: hidden !important;
  width: 360px !important;
  min-width: 360px !important;
  max-width: 360px !important;
}

/* Cookies notification: Adjust size for smaller windows */
._9o-g {
  height: 290px !important;
}
._9xo5 {
  padding-top: 12px !important;
}
._59s7._9l2g {
  height: 498px !important;
}

/* Cookies notification: Remove "allow all cookies" button */
._42ft._4jy0._9xo7._4jy3._4jy1.selected._51sy {
  display: none;
}

/* Cookies notification: accept button */
._42ft._4jy0._9xo6._4jy3._4jy1.selected._51sy {
  background-color: #1877f2 !important;
  color: var(--white) !important;
}

/* Hide disabled scrollbar on the right side */
body::-webkit-scrollbar {
  display: none;
}

/* A utility class for temporarily hiding all dropdown menus */
html.hide-dropdowns [role="menu"].x1n2onr6.xi5betq {
  visibility: hidden !important;
}

/* A utility class for temporarily hiding preferences window */
html.hide-preferences-window
  div[class="x9f619 x1n2onr6 x1ja2u2z"]
  > div:nth-of-type(3)
  > div
  > div {
  display: none;
}

/* -- Private mode -- */
/* Preferences button: profile picture */
html.private-mode
  [role="navigation"]
  .qi72231t.o9w3sbdw.nu7423ey.tav9wjvu.flwp5yud.tghlliq5.gkg15gwv.s9ok87oh.s9ljgwtm.lxqftegz.bf1zulr9.frfouenu.bonavkto.djs4p424.r7bn319e.bdao358l.fsf7x5fv.tgm57n0e.jez8cy9q.s5oniofx.m8h3af8h.l7ghb35v.kjdc1dyq.kmwttqpk.dnr7xe2t.aeinzg81.srn514ro.oxkhqvkx.rl78xhln.nch0832m.om3e55n1.cr00lzj9.rn8ck1ys.s3jn8y49.g4tp4svg.o9erhkwx.dzqi5evh.hupbnkgi.hvb2xoa8.fxk3tzhb.jl2a5g8c.f14ij5to.l3ldwz01.icdlwmnq {
  filter: blur(5px);
}
/* Preferences: profile picture */
html.private-mode
  .alzwoclg.b0eko5f3.q46jt4gp.r5g9zsuq
  .aglvbi8b.om3e55n1.i8zpp7h3.g4tp4svg {
  filter: blur(5px);
}
/* Preferences: account name */
html.private-mode
  [href^="https://www.facebook.com/1"]
  .b6ax4al1.i54nktwv.z2vv26z9.om3e55n1.gvxzyvdx.aeinzg81.t7p7dqev.gh25dzvf.gem102v4.ncib64c9.mrvwc6qr.sx8pxkcf.f597kf1v.cpcgwwas.ocv3nf92.k1z55t6l.tpi2lg9u.pbevjfx6.ztn2w49o.f5mw3jnl.ib8x7mpr.qc5lal2y {
  filter: blur(5px);
}
/* Chat list: name, profile picture and last message */
html.private-mode [role="navigation"] [role="row"] .b6ax4al1.gvxzyvdx {
  filter: blur(5px);
}
/* Chat list: person tiny heads */
html.private-mode [role="row"] .aglvbi8b.om3e55n1.i8zpp7h3.g4tp4svg {
  filter: blur(3px);
}
/* Conversation: titlebar profile picture */
html.private-mode .b6ax4al1.gvxzyvdx.dgxim35p.p9wrh9lq {
  filter: blur(5px);
}
/* Conversation: sender profile picture */
html.private-mode .mfclru0v.p9wrh9lq.pytsy3co.aglvbi8b {
  filter: blur(5px);
}
/* Conversation: name & last seen */
html.private-mode
  [role="main"]
  .alzwoclg.cqf1kptm.hael596l.jcxyg2ei.cgu29s5g.dn6jqzda {
  filter: blur(5px);
}
/* Conversation: read indicator */
html.private-mode
  [role="main"]
  .iec8yc8l.b7mnygb8.dktd5soj.f14ij5to.qmqpeqxj.e7u6y3za.qwcclf47.nmlomj2f {
  filter: blur(5px);
}
/* Conversation: name & details at the beginning */
html.private-mode
  .h6ft4zvz.rj2hsocd.aesu6q9g.e4ay1f3w
  .hsphh064.pk1vzqw1.hxfwr5lz.qc5lal2y {
  filter: blur(5px);
}
/* Right sidebar: profile picture */
html.private-mode .aglvbi8b.om3e55n1.i8zpp7h3.g4tp4svg {
  filter: blur(5px);
}
/* Right sidebar: name */
html.private-mode
  [role="main"]
  .qi72231t.nu7423ey.n3hqoq4p.r86q59rh.b3qcqh3k.fq87ekyn.bdao358l.fsf7x5fv.rse6dlih.s5oniofx.m8h3af8h.l7ghb35v.kjdc1dyq.kmwttqpk.srn514ro.oxkhqvkx.rl78xhln.nch0832m.cr00lzj9.rn8ck1ys.s3jn8y49.icdlwmnq.jxuftiz4.cxfqmxzd {
  filter: blur(5px);
}
/* Right sidebar: active status */
html.private-mode
  [role="main"]
  .b6ax4al1.i54nktwv.z2vv26z9.om3e55n1.gvxzyvdx.aeinzg81.t7p7dqev.gh25dzvf.gem102v4.ncib64c9.mrvwc6qr.sx8pxkcf.f597kf1v.cpcgwwas.ocv3nf92.nfkogyam.gh55jysx.rtxb060y.hsphh064.pk1vzqw1.hxfwr5lz.qc5lal2y {
  filter: blur(5px);
}
/* New conversation: profile picture */
html.private-mode
  .mfclru0v.pytsy3co.qmqpeqxj.e7u6y3za.qwcclf47.nmlomj2f.i8zpp7h3.p9wrh9lq {
  filter: blur(5px);
}
/* New conversation: profile picture (groups) */
html.private-mode .qmqpeqxj.e7u6y3za.qwcclf47.nmlomj2f.s8sjc6am {
  filter: blur(5px);
}
/* Calls: incoming call dialog account name */
html.private-mode
  .b6ax4al1.i54nktwv.z2vv26z9.om3e55n1.gvxzyvdx.aeinzg81.t7p7dqev.gh25dzvf.gem102v4.ncib64c9.mrvwc6qr.sx8pxkcf.f597kf1v.cpcgwwas.ocv3nf92.qntmu8s7.o48pnaf2.pbevjfx6.hsphh064.m2nijcs8.pc9ouhwb.qc5lal2y,
html.private-mode
  .gvxzyvdx.aeinzg81.t7p7dqev.gh25dzvf.rse6dlih.ocv3nf92.nfkogyam.innypi6y.rtxb060y.qc5lal2y {
  filter: blur(10px);
}

/* Force max-width on videos */
.ni8dbmo4.stjgntxs.g5ia77u1.ii04i59q.j83agx80.cbu4d94t.ll8tlv6m > span,
.l9j0dhe7.km676qkl.cxmmr5t8.myj7ivm5.hcukyx3x,
.opwvks06.hop1g133.linmgsc8.t63ysoy8.qutah8gn.ni8dbmo4.stjgntxs.ktxn16wu.jz9ahs1c.efwgsih4.e72ty7fz.qmr60zad.qlfml3jp.inkptoze {
  max-width: 100%;
}

/* Hide the "Messenger App for Mac/Windows" banner in chat list */
.x9f619.x1n2onr6.x1ja2u2z.x78zum5.x1r8uery.xs83m0k.xeuugli.x1qughib.x6s0dn4.xozqiw3.x1q0g3np.xknmibj.x1c4vz4f.xt55aet.xexx8yu.xc73u3c.x18d9i69.x5ib6vp.x1lku1pv.xzd29fr {
  display: none;
}
/* Hide the "Messenger for Mac/Windows" menu item and separator in Messenger settings */
.x4k7w5x.x1h91t0o.x1beo9mf.xaigb6o.x12ejxvf.x3igimt.xarpa2k.xedcshv.x1lytzrv.x1t2pt76.x7ja8zs.x1n2onr6.x1qrby5j.x1jfb8zj
  > div
  > div:last-of-type
  > a {
  display: none;
}

/* -- Sidebar views -- */
/* Hidden: Hide sidebar */
html.sidebar-hidden
  .bdao358l.om3e55n1.alzwoclg.cqf1kptm.gvxzyvdx.aeinzg81.jez8cy9q.fawcizw8.sl4bvocy.mm98tyaj.b0ur3jhr.f76nr8pf {
  display: none;
}

/* Narrow: Hide preferences button */
html.sidebar-force-narrow .pvreidsc.r227ecj6.n68fow1o.gt60zsk1.lth9pzmp {
  display: none;
}
/* Narrow: Hide conversation previews */
html.sidebar-force-narrow
  .bdao358l.om3e55n1.g4tp4svg.alzwoclg.cqf1kptm.jez8cy9q.gvxzyvdx.aeinzg81.cgu29s5g {
  display: none;
}
/* Narrow: Hide search bar */
html.sidebar-force-narrow
  .bdao358l.om3e55n1.g4tp4svg.r227ecj6.gt60zsk1.rj2hsocd.f9xcifuu {
  display: none;
}
/* Narrow: Width of conversation list */
html.sidebar-force-narrow
  .bdao358l.om3e55n1.alzwoclg.cqf1kptm.gvxzyvdx.aeinzg81.jez8cy9q.fawcizw8.sl4bvocy.mm98tyaj.b0ur3jhr.f76nr8pf {
  width: 80px;
}

/* -- Toggle message buttons -- */
body
  .qi72231t.o9w3sbdw.nu7423ey.tav9wjvu.flwp5yud.tghlliq5.gkg15gwv.s9ok87oh.s9ljgwtm.lxqftegz.bf1zulr9.frfouenu.bonavkto.djs4p424.r7bn319e.bdao358l.fsf7x5fv.tgm57n0e.jez8cy9q.s5oniofx.m8h3af8h.l7ghb35v.kjdc1dyq.dnr7xe2t.aeinzg81.om3e55n1.cr00lzj9.rn8ck1ys.s3jn8y49.g4tp4svg.o9erhkwx.dzqi5evh.hupbnkgi.hvb2xoa8.fxk3tzhb.jl2a5g8c.f14ij5to.l3ldwz01.icdlwmnq.q46jt4gp.b0eko5f3.r5g9zsuq.fwlpnqze.jbg88c62,
body
  .s8sjc6am.z6erz7xo.alzwoclg.jcxyg2ei.i85zmo3j.b0ur3jhr.kjdc1dyq.tjkoo78o.iwr3bmeu.qgj99rie {
  display: flex;
}

body.show-message-buttons
  .qi72231t.o9w3sbdw.nu7423ey.tav9wjvu.flwp5yud.tghlliq5.gkg15gwv.s9ok87oh.s9ljgwtm.lxqftegz.bf1zulr9.frfouenu.bonavkto.djs4p424.r7bn319e.bdao358l.fsf7x5fv.tgm57n0e.jez8cy9q.s5oniofx.m8h3af8h.l7ghb35v.kjdc1dyq.dnr7xe2t.aeinzg81.om3e55n1.cr00lzj9.rn8ck1ys.s3jn8y49.g4tp4svg.o9erhkwx.dzqi5evh.hupbnkgi.hvb2xoa8.fxk3tzhb.jl2a5g8c.f14ij5to.l3ldwz01.icdlwmnq.q46jt4gp.b0eko5f3.r5g9zsuq.fwlpnqze.jbg88c62,
body.show-message-buttons
  .s8sjc6am.z6erz7xo.alzwoclg.jcxyg2ei.i85zmo3j.b0ur3jhr.kjdc1dyq.tjkoo78o.iwr3bmeu.qgj99rie {
  display: none;
}

body.show-message-buttons .cgu29s5g.alzwoclg.oo5upp5e {
  margin-left: 15px !important;
}

Step 4: Autostart on Login (Optional)

While you can easily add this via Plasma's System Settings > Autostart GUI, a quick symlink handles it directly from the terminal:

ln -s ~/.local/share/applications/brave-messenger.desktop ~/.config/autostart/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment