[{"data":1,"prerenderedAt":258},["ShallowReactive",2],{"seo-verification":3,"blog-heberger-excalidraw-vps-2-ma-en":6,"promo-bar-likely":249},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-heberger-excalidraw-vps-2-ma-en",{"id":9,"slug":10,"slugs":11,"title":14,"excerpt":15,"readTime":16,"views":17,"isPinned":18,"noindex":18,"publishedAt":19,"updatedAt":20,"category":21,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":190,"ctaBody":191,"ctaButton":192,"ctaUrl":193,"relatedPosts":194},349,"heberger-excalidraw-vps-2",{"fr":12,"en":10,"ar":10,"es":13},"heberger-excalidraw-vps","alojar-excalidraw-en-un-vps-pizarra-colaborativa-sin-suscripcion","Self-Hosting Excalidraw on a VPS: Open Source Whiteboard","Deploy Excalidraw on your VPS: MIT whiteboard, real-time on your own server, and what stays with third parties (Firebase, share links).",15,10,false,"2026-09-11T00:00:00+00:00","2026-11-09T20:55:15+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},7,"Self-hosting","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[28],{"id":22,"name":23,"slug":24,"color":25,"icon":26},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fheberger-excalidraw-vps-poster.svg","Miro, FigJam, Lucidspark: SaaS whiteboards charge per seat, store your mockups on their servers and cap members by plan. Excalidraw is the open-source alternative (MIT): a hand-drawn-style collaborative whiteboard whose two components — the React interface and the WebSocket room server — self-host on a VPS in two Docker containers. This guide shows how to deploy them, wire nginx for WebSockets, and states plainly what a standard installation still leaves with third-party services (Firebase, share links).",[34,38,48,51,54,62,81,84,91,131,134,137,146,150,184,187],{"type":35,"title":36,"body":37},"h2","Why self-host Excalidraw instead of using the public version","The public version at excalidraw.com works fine for quick solo sketches. It routes real-time collaboration sessions through a server managed by Excalidraw s.r.o. That is acceptable for an ad-hoc brainstorm. It is much less so when the boards contain client flow mockups, internal system architecture diagrams or wireframes covered by an NDA.\n\nSelf-hosting Excalidraw shifts the control boundary to your own infrastructure. Real-time traffic goes through **your** WebSocket server, on **your** domain; what a standard installation still leaves with a third party (the saved scene, share links) is detailed below. You decide who connects — via IP allowlist, OIDC SSO or HTTP Basic Auth in front of nginx. And since both components are published under the MIT licence, no commercial restriction applies regardless of how many clients or collaborators work on the instance.",{"type":39,"title":40,"items":41},"ul","Concrete benefits",[42,43,44,45,46,47],"**Zero software subscription** — both components (interface and collaboration server) are MIT. You pay for the VPS, nothing else.","**Mockup confidentiality** — live drawing stays on your infrastructure. The saved scene and a room's images still need handling (Firebase by default): see “What really works when self-hosting”.","**Access under your control** — IP allowlist, OIDC SSO or HTTP Basic Auth in front of nginx depending on the required isolation level.","**Sessions and members scale with VPS RAM** — no per-plan cap; the only limit is server RAM, and `excalidraw-room` is a lightweight Node.js service.","**Optional persistence** — mount a Docker volume or connect an S3-compatible bucket to archive boards exported as JSON.","**Integration into a self-hosted stack** — an Excalidraw instance alongside Penpot, Mattermost or Docmost closes the SaaS perimeter for an entire agency.",{"type":35,"title":49,"body":50},"Architecture: two containers, distinct roles","Excalidraw splits what most people consider a single tool into two independent components:\n\n- **`excalidraw\u002Fexcalidraw`** — the compiled React interface, served as a static site by nginx inside the container. It runs no application server. Its service addresses (room, Firebase, sharing) are `VITE_APP_*` variables read at **compile time** and baked into the JavaScript bundle: changing them on a running container has no effect.\n\n- **`excalidraw\u002Fexcalidraw-room`** — a Node.js Socket.IO server that relays drawing events in memory between participants in the same session. It is **stateless**: it persists nothing and forgets everything on restart. A room's saved scene does not go through it (see below). Its Docker Hub image has not been republished since December 2023 and its upstream Dockerfile starts from Node 12: keep it behind nginx, on the Docker network, with no published port.\n\nPractical consequence: the official Docker image was built with excalidraw.com's addresses. To target your own `excalidraw-room`, you must **build your own image** after editing `VITE_APP_WS_SERVER_URL` in `.env.production`.",{"type":35,"title":52,"body":53},"Prerequisites","The ServOrbit VPS Solo (2 vCPU, 4 GB RAM) covers the standard case: the static interface is nearly zero-load, and `excalidraw-room` consumes less than 256 MB under normal traffic. With ten concurrent collaborators, you will stay well under half the available RAM.\n\n**What you need before starting:**",{"type":39,"title":55,"items":56},"Prerequisites checklist",[57,58,59,60,61],"A VPS with at least 1 vCPU and 512 MB RAM (1 GB recommended for a team).","Docker Engine and Docker Compose Plugin installed (`docker compose version` to verify).","A domain name pointed at the VPS IP — without TLS, WebSockets are blocked by modern browsers.","Root SSH access or a user with `sudo` rights.","A valid TLS certificate — ServOrbit configures Let's Encrypt automatically.",{"type":63,"title":64,"steps":65},"steps","Deploy Excalidraw in 5 steps",[66,69,72,75,78],{"title":67,"body":68},"Create the VPS and install Docker","Provision an Ubuntu 24.04 VPS from your ServOrbit dashboard. Once connected over SSH, if Docker is not yet installed, run:\n\n```bash\ncurl -fsSL https:\u002F\u002Fget.docker.com | sh\n```\n\nVerify Docker Compose Plugin responds before continuing:\n\n```bash\ndocker compose version\n```",{"title":70,"body":71},"Build the image with your collaboration URL","Clone the official repository, then set the room address **in the repository's `.env.production` file** before building. Replace `collab.yourdomain.com` with the subdomain you allocate to `excalidraw-room`:\n\n`git clone https:\u002F\u002Fgithub.com\u002Fexcalidraw\u002Fexcalidraw.git`\n`cd excalidraw`\n`sed -i 's|^VITE_APP_WS_SERVER_URL=.*|VITE_APP_WS_SERVER_URL=https:\u002F\u002Fcollab.yourdomain.com|' .env.production`\n`docker build -t my-excalidraw:latest .`\n\nWhy not `--build-arg`? The upstream Dockerfile declares no `ARG` for the `VITE_APP_*` variables: a `--build-arg VITE_APP_WS_SERVER_URL=…` never reaches the build command, the image builds normally and keeps pointing at Excalidraw's server. The upstream `.dockerignore` also admits only `.env.development` and `.env.production`, so a `.env.production.local` would be ignored. The address is baked into the bundle, so changing domain means rebuilding.\n\nCheck the result: `docker run --rm --entrypoint sh my-excalidraw:latest -c \"grep -rl oss-collab.excalidraw.com \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml || echo clean\"` must print `clean`. The official `excalidraw\u002Fexcalidraw` image is fine for local trials, but it targets Excalidraw's public services.",{"title":73,"body":74},"Write the docker-compose.yml file","Create a working directory and write the following file. Both services listen internally; nginx (next step) is the only public entry point:\n\n```bash\nmkdir ~\u002Fexcalidraw-stack && cd ~\u002Fexcalidraw-stack\n```\n\n`docker-compose.yml` contents:\n\n```bash\nservices:\n  excalidraw:\n    image: my-excalidraw:latest\n    restart: unless-stopped\n    networks:\n      - excalidraw\n\n  excalidraw-room:\n    image: excalidraw\u002Fexcalidraw-room:latest\n    environment:\n      - CORS_ORIGIN=https:\u002F\u002Fdraw.yourdomain.com\n    restart: unless-stopped\n    networks:\n      - excalidraw\n\nnetworks:\n  excalidraw:\n```\n\nStart the stack:\n\n```bash\ndocker compose up -d\n```",{"title":76,"body":77},"Configure nginx with WebSocket headers","This is the step where most deployments silently fail: without the `Upgrade` and `Connection` headers, the browser opens a plain HTTP connection instead of a WebSocket, and collaboration appears not to work with no visible error message.\n\nnginx block for the Excalidraw frontend (`draw.yourdomain.com`):\n\n```bash\nserver {\n    listen 443 ssl;\n    server_name draw.yourdomain.com;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002Fexcalidraw:80;\n        proxy_set_header Host $host;\n    }\n}\n```\n\nnginx block for the room server (`collab.yourdomain.com`):\n\n```bash\nserver {\n    listen 443 ssl;\n    server_name collab.yourdomain.com;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002Fexcalidraw-room:80;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_set_header Host $host;\n        proxy_read_timeout 86400s;\n    }\n}\n```\n\nReload nginx (`nginx -s reload`) after placing the blocks.",{"title":79,"body":80},"Test real-time collaboration","Open `https:\u002F\u002Fdraw.yourdomain.com` in two tabs or two different browsers. In the toolbar, click **Live collaboration** and create a session. Copy the session link into the second tab.\n\nDraw something in the first tab: the stroke should appear in the second in real time. If it does not, check the WebSocket headers in nginx first (browser network devtools show whether the connection upgraded to `101 Switching Protocols`). A `200` status on the WebSocket request means nginx did not pass the `Upgrade` headers.\n\nThen open the browser's network tab: the real-time connection must target `collab.yourdomain.com`, never oss-collab.excalidraw.com. What Firebase receives is covered in the next section.",{"type":35,"title":82,"body":83},"What really works when self-hosting","Let us be precise: “two containers and you are done” is the shortcut this kind of guide repeats most often. The upstream umbrella thread (excalidraw\u002Fexcalidraw, issue no. 1772, open since June 2020 and still active in October 2026) sums up three walls, which we cross-checked against the code and the repository's `.env` files.\n\n**Wall 1 — addresses are fixed at build time.** The addresses of the collaboration server, the sharing service and the Firebase project are `VITE_APP_*` variables read by Vite during the build. The official `excalidraw\u002Fexcalidraw` image was built with the values from `.env.production`: it therefore still talks to excalidraw.com's services. A variable passed to `docker run` changes nothing, and the upstream Dockerfile declares no `ARG` to relay one into the build.\n\n**Wall 2 — collaboration is half local.** Real-time traffic (who draws what, live) goes through `excalidraw-room`, which you host. But the saved scene and the images pasted into a room go to Firebase: the code calls `saveToFirebase` and `saveFilesToFirebase`, using the configuration in `VITE_APP_FIREBASE_CONFIG`. As long as that variable keeps the upstream value, this data (encrypted in the browser with the room key) is stored in Excalidraw's Firebase project, not with you. That reconciles the contradictory reports in the thread: one finds that collaboration fails with `VITE_APP_FIREBASE_CONFIG='{}'`, another that Jitsi Meet removed the Firebase part and real-time works with the room alone. Live drawing can do without Firebase; saving and resuming cannot.\n\n**Wall 3 — share links need a storage server the project does not publish.** A `#json=` link is created by a request to `VITE_APP_BACKEND_V2_POST_URL` and read back through `VITE_APP_BACKEND_V2_GET_URL`, by default json.excalidraw.com. The thread mentions community rewrites (one in Next.js on S3, another on S3-compatible storage) but names none as official.",{"type":39,"title":85,"items":86},"Three possible setups, and what each leaves with a third party",[87,88,89,90],"**Setup A — room only (the one in this guide).** You change `VITE_APP_WS_SERVER_URL` and nothing else. Live drawing goes through your server; the saved scene and the rooms' images are still written to Excalidraw's Firebase. Acceptable for low-sensitivity boards, not to be presented as “nothing with a third party”.","**Setup B — room + your own Firebase project.** You create a Firebase project of your own and put its JSON configuration in `VITE_APP_FIREBASE_CONFIG`. The code reads only that variable; we have not deployed this end to end, and Firebase remains a Google service, not self-hosting in the strict sense.","**Setup C — solo instance.** You serve the interface alone, with no room and no link: everyone draws, exports to `.excalidraw` or an image, and archives the files with you. Nothing goes to a third party for collaboration, since there is none.","**What does not exist on the official side.** No open storage server for `#json=` links, and no option that moves the whole perimeter to your domain through a single runtime variable. If your requirement is “no data with a third party” with collaboration and sharing, the honest answer is adaptation or fork work, not an installation.",{"type":92,"title":93,"headers":94,"rows":98},"comparison","Variable → function → what breaks without it",[95,96,97],"Variable","Function","What breaks without it",[99,103,107,111,115,119,123,127],[100,101,102],"`VITE_APP_WS_SERVER_URL` (build time)","Address of the Socket.IO real-time server (`excalidraw-room`).","Upstream value kept: your sessions go through oss-collab.excalidraw.com. Unreachable address: collaboration does not start.",[104,105,106],"`VITE_APP_FIREBASE_CONFIG` (build time)","JSON configuration of the Firebase project: a room's saved scene and pasted images.","Upstream value: that data stays with Excalidraw. Empty or invalid (`{}` included): saving and resuming a room fail, and according to one report in the thread so does collaboration. Unreadable JSON logs `Error JSON parsing firebase config`.",[108,109,110],"`VITE_APP_BACKEND_V2_POST_URL` (build time)","Creating a `#json=` share link (upload of the encrypted scene).","Upstream value: the link is created at json.excalidraw.com. Address without a compatible server: link creation fails.",[112,113,114],"`VITE_APP_BACKEND_V2_GET_URL` (build time)","Reading back a `#json=` link when it is opened.","Upstream value: the link is read from Excalidraw. Address without a compatible server: opening the link fails.",[116,117,118],"`VITE_APP_DISABLE_SENTRY` (build time)","Disables sending error reports to Sentry.","Nothing breaks; without it, the app may send error reports to a third party. The upstream `build:app:docker` script already sets it to `true`.",[120,121,122],"`VITE_APP_DISABLE_PREVENT_UNLOAD` (build time)","Removes the warning before leaving a room whose saving is not finished.","Nothing breaks, but closing the tab no longer warns. Keep it for debugging.",[124,125,126],"`CORS_ORIGIN` (runtime, `excalidraw-room`)","Origin allowed to open a connection to the room server.","Absent: the default is `*`, any web page can connect. Set `https:\u002F\u002Fdraw.yourdomain.com`.",[128,129,130],"`PORT` (runtime, `excalidraw-room`)","Listening port of the room server.","Absent: listens on port 80 outside development mode, which is what this guide's nginx blocks assume. If you change it, `proxy_pass` must follow.",{"type":35,"title":132,"body":133},"Checking who receives what","The only way to know what leaves your instance is to look. Open the browser's network tab, start a collaboration session, draw, paste an image, then create a share link. Three families of destinations can be read: your room subdomain (real time, expected); Firebase's `googleapis.com` domains (saved scene and images, expected with the upstream configuration, to be eliminated if you thought otherwise); json.excalidraw.com (link sharing). This inspection is the acceptance test of the setup you chose: without it, “on my server” remains a hypothesis.\n\nFinally, remember that the room server authenticates nobody: `CORS_ORIGIN` limits which web pages may connect to it, not which people. Participant identity is handled in front of the interface (Basic Auth, SSO), as described further down.",{"type":35,"title":135,"body":136},"Troubleshooting: collaboration will not start, or remembers nothing","The symptoms below follow from the code and the upstream thread; no message is reproduced other than those read in the repository.",{"type":39,"title":138,"items":139},"Symptoms, causes, remedies",[140,141,142,143,144,145],"**The session goes to oss-collab.excalidraw.com (network tab) although you built your own image.** Cause: the address was not picked up at build time (`--build-arg` has no effect, `.env.production.local` is ignored by the `.dockerignore`). Remedy: edit `.env.production`, rebuild, replay the `grep` check from step 2. A domain change follows the same rule.","**The browser's connection to the room is refused.** Frequent cause after setting `CORS_ORIGIN`: the origin does not exactly match the page's (`http` scheme instead of `https`, port, trailing slash). Remedy: the value must be the interface's exact origin, for example `https:\u002F\u002Fdraw.yourdomain.com`.","**Strokes appear live, but a participant who joins later, or after a room restart, does not find the content or the images.** Cause: the scene and images are saved through Firebase, not by `excalidraw-room`, which retains nothing. If `VITE_APP_FIREBASE_CONFIG` is empty or unreachable, nothing is read back. Remedy: choose setup A or B above.","**Warning `Error JSON parsing firebase config. Supplied value:` in the browser console.** Cause: `VITE_APP_FIREBASE_CONFIG` is not valid JSON, most often because of badly protected quotes or a line break in the file. Remedy: JSON on a single line, in single quotes in `.env.production`, as in the upstream file.","**Link sharing fails, or the link produced points to json.excalidraw.com.** Cause: `VITE_APP_BACKEND_V2_POST_URL` and `VITE_APP_BACKEND_V2_GET_URL` were not changed, or point to a server that does not implement the expected API. Remedy: keep the default knowingly, or exchange `.excalidraw` files.","**Encryption or key-generation error on a local network over `http:\u002F\u002F`.** Cause: the browser's encryption API (`window.crypto`) is only exposed in a secure context; the upstream thread flags this trap for local-network self-hosting. Remedy: serve the interface over HTTPS (or on `localhost`), as the TLS prerequisite above requires.",{"type":147,"title":148,"body":149},"tip","Board persistence: what is actually saved","By default, `excalidraw-room` is fully stateless: if the server restarts, the relay starts from scratch. A room's saved scene lives elsewhere (Firebase, see above), and each participant also keeps their drawing in their browser's `localStorage`.\n\n**Option 1 — Manual export of `.excalidraw` files.** The interface's export menu produces a `.excalidraw` file (or an image) that can be re-imported at any time. Excalidraw exposes no export API to call from a cron job: it is a gesture made in the browser, whose file you then drop into a volume or a git repository.\n\n**Option 2 — S3-compatible bucket for archiving.** ServOrbit offers S3-compatible object storage. Copy the exported files there with the tool of your choice (`rclone`, `aws s3 cp`); restoring means re-importing the last file. Excalidraw itself does not write to S3.",{"type":92,"title":151,"headers":152,"rows":157},"Self-hosted Excalidraw vs SaaS alternatives",[153,154,155,156],"Criteria","Excalidraw (self-hosted)","Miro","FigJam",[158,162,167,171,175,179],[159,160,161,161],"Cost per user","None (VPS only)","Paid per seat",[163,164,165,166],"Data hosted at","Your infrastructure (real-time); Excalidraw's Firebase by default for the saved scene","Miro Inc.","Adobe \u002F Figma",[168,169,170,170],"Concurrent members","RAM-bound","Plan-limited",[172,173,174,174],"Software licence","MIT (open source)","Proprietary",[176,177,178,178],"Self-hostable","Partly: two containers, plus Firebase and share links to deal with","No",[180,181,182,183],"Access control","IP \u002F SSO \u002F Basic Auth","SSO (Pro plans)","SSO (Edu+ plans)",{"type":35,"title":185,"body":186},"Going further: SSO and IP allowlists","For an agency whose clients have strict confidentiality requirements, exposing Excalidraw on a public subdomain is not always acceptable. Two common configurations harden access without modifying Excalidraw itself.\n\n**HTTP Basic Auth via nginx.** Add an `auth_basic` directive in front of the frontend `location \u002F` block. Anyone attempting to open the interface must authenticate before the React app even loads. Simple to set up, sufficient for internal projects.\n\n**IP allowlist.** If collaborators connect from fixed IPs or a corporate VPN, an `allow`\u002F`deny` block in nginx is enough to close the instance to the rest of the Internet:\n\n```bash\nallow 203.0.113.0\u002F24;\nallow 198.51.100.42;\ndeny all;\n```\n\n**OIDC SSO via an authenticating reverse proxy.** For teams that already have an identity provider (Keycloak, Authelia, Authentik), an authenticating proxy such as Oauth2-Proxy or Authelia placed in front of nginx delegates authentication to the existing SSO. Excalidraw does not need to know that an additional auth layer exists.",{"type":35,"title":188,"body":189},"Integration in a self-hosted stack","Excalidraw integrates naturally into a self-hosted tool stack. If you have already deployed Mattermost for team communication, you can paste an Excalidraw session link into a channel and invite collaborators to join the board directly. If Penpot covers high-fidelity design, Excalidraw handles upstream work — quick wireframes, flow diagrams and brainstorming sessions — before designs enter Penpot.\n\nThis complementarity is the real argument against SaaS: each tool stays within its area of expertise, without a platform subscription billing for features you do not need.","One platform for your VPS, domain and backups","ServOrbit.com brings VPS, domain and backups together on your account: deploy Excalidraw for your team from your client area.","Explore the agency offer","\u002Fsolutions\u002Fagences",[195,220,239],{"id":196,"slug":197,"slugs":198,"title":202,"excerpt":203,"readTime":204,"views":205,"isPinned":18,"noindex":18,"publishedAt":206,"updatedAt":207,"category":208,"categories":214,"featuredImage":29,"bgImage":30,"posterImage":216,"relatedSolution":217},193,"self-host-penpot-open-source-figma-alternative-on-your-vps",{"fr":199,"en":197,"ar":200,"es":201},"self-host-penpot-vps","استضافة-penpot-على-vps-بديل-figma-مفتوح-المصدر","alojar-penpot-en-un-vps","Self-host Penpot: open-source Figma alternative on your VPS","Deploy Penpot on a ServOrbit VPS for a full collaborative design tool — vector prototyping, components, developer handoff — no Figma subscription, no third-party data.",12,1,"2026-07-27T00:00:00+00:00","2026-11-04T16:30:26+00:00",{"id":209,"name":210,"slug":211,"color":212,"icon":213},4,"Development","developpement","bg-warning\u002F10 text-warning","dev",[215],{"id":209,"name":210,"slug":211,"color":212,"icon":213},"\u002Fblog\u002Fcovers\u002Fself-host-penpot-vps-poster.svg",{"categorySlug":218,"appSlug":219},"collaboration-productivity","penpot",{"id":221,"slug":222,"slugs":223,"title":227,"excerpt":228,"readTime":229,"views":230,"isPinned":18,"noindex":18,"publishedAt":231,"updatedAt":232,"category":233,"categories":234,"featuredImage":29,"bgImage":30,"posterImage":236,"relatedSolution":237},76,"host-mattermost-on-your-own-vps",{"fr":224,"en":222,"ar":225,"es":226},"heberger-mattermost","استضافة-mattermost-على-خادم-vps-الخاص-بك","alojar-mattermost-en-un-vps","Host Mattermost on your own VPS","Complete 2026 guide: deploy Mattermost v10\u002Fv11 on VPS with Docker, PostgreSQL, SSL, integrations and backups. Self-hosted alternative to Slack.",9,5,"2026-04-05T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},[235],{"id":22,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fheberger-mattermost-poster.svg",{"categorySlug":24,"appSlug":238},"mattermost",{"id":240,"slug":241,"slugs":242,"title":246,"excerpt":247,"readTime":248,"views":209,"isPinned":18,"noindex":249,"publishedAt":250,"updatedAt":251,"category":252,"categories":253,"featuredImage":29,"bgImage":30,"posterImage":255,"relatedSolution":256},302,"planka-self-host-an-open-source-kanban-board-on-your-vps",{"fr":243,"en":241,"ar":244,"es":245},"self-host-planka-vps","planka-نشر-لوحة-kanban-مفتوحة-المصدر-على-vps","planka-tablero-kanban-open-source-autoalojado-en-vps","Planka: Self-Host an Open-Source Kanban Board on Your VPS","Planka: self-hosted Kanban board for dev teams. Open-source alternative to Trello (AGPL), ~12k GitHub stars — deploy on your VPS in minutes.",3,true,"2026-01-13T00:00:00+00:00","2026-11-04T16:30:27+00:00",{"id":22,"name":23,"slug":24,"color":25,"icon":26},[254],{"id":22,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fself-host-planka-vps-poster.svg",{"categorySlug":218,"appSlug":257},"planka",1794270408302]