{"@context":["https://www.w3.org/ns/activitystreams",{"Hashtag":"as:Hashtag","sensitive":"as:sensitive","dcterms":"http://purl.org/dc/terms/","gts":"https://gotosocial.org/ns#","schema":"http://schema.org/","exifData":"schema:exifData","PropertyValue":"schema:PropertyValue","interactionPolicy":{"@id":"gts:interactionPolicy","@type":"@id"},"canQuote":{"@id":"gts:canQuote","@type":"@id"},"canReply":{"@id":"gts:canReply","@type":"@id"},"canLike":{"@id":"gts:canLike","@type":"@id"},"canAnnounce":{"@id":"gts:canAnnounce","@type":"@id"},"automaticApproval":{"@id":"gts:automaticApproval","@type":"@id"},"manualApproval":{"@id":"gts:manualApproval","@type":"@id"},"always":{"@id":"gts:always","@type":"@id"},"toot":"http://joinmastodon.org/ns#","blurhash":"toot:blurhash"}],"id":"https://naiwaen.debuggingsoft.com/?p=49758","type":"Note","attachment":[{"type":"Image","url":"https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_cover.webp?fit=1024%2C585\u0026ssl=1","mediaType":"image/webp"},{"type":"Image","url":"https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_package.webp?fit=1024%2C646\u0026ssl=1","mediaType":"image/webp"},{"type":"Image","url":"https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_bunlock.webp?fit=1024%2C628\u0026ssl=1","mediaType":"image/webp"}],"attributedTo":"https://naiwaen.debuggingsoft.com/?author=1","content":"\u003Ch2\u003EFixed Cannot find module /app/node_modules/xlsx/dist/cpexcel.js\u003C/h2\u003E\n\n\u003Cp\u003EToday I want to share a problem I encountered when integrating SheetJS with Nuxt specifically in cases without authentication, accessing the path directly works fine. But when the path requires \u003Cstrong\u003EServer-Side Authentication\u003C/strong\u003E, it throws the error below.\u003C/p\u003E\u003Cpre\u003ECannot find module '/app/node_modules/xlsx/dist/cpexcel.js' from '/app/server/chunks/build/index-64cha0zE.mjs'\u003C/pre\u003E\u003Ch4\u003EWhy\u003C/h4\u003E\u003Cul\u003E\u003Cli\u003ESheetJS was designed to separate the codepage table into an optional file in order to reduce bundle size.SheetJS was designed to separate the codepage table into an optional file in order to reduce bundle size. \u003C/li\u003E\u003Cli\u003EThe legacy version (0.18.x) still relies on a CJS build that loads cpexcel via a dynamic \u003Ccode\u003Erequire() \u003C/code\u003Ewrapped in a \u003Ccode\u003Etry/catch\u003C/code\u003E block. As a result, when Nitro bundles the server output using Rollup and node-file-trace, \u003Cstrong\u003ERollup treats\u003C/strong\u003E the dynamic require() inside the try/catch \u003Cstrong\u003Eas optional code and skips it\u003C/strong\u003E. so \u003Cstrong\u003E\u003Cem\u003Ecpexcel.js\u003C/em\u003E\u003C/strong\u003E never gets copied into \u003Ccode\u003E.output\u003C/code\u003E. At runtime, the path resolution is correct, but the file is simply not there because it was never included during the build.\u003C/li\u003E\u003C/ul\u003E\u003Ch4\u003ESolution\u003C/h4\u003E\u003Cp\u003EUpgrading the SheetJS library from 0.18.5 \u2192 0.20.3 has two approaches, but for versions after 18, SheetJS requires you to pull the package directly from \u003Cstrong\u003E\u003Ca href=\u0022https://cdn.sheetjs.com/\u0022 rel=\u0022noopener\u0022\u003Ehttps://cdn.sheetjs.com/\u003C/a\u003E\u003C/strong\u003E instead.\u003C/p\u003E\u003Ch5\u003E- First Solution (Public to Private Repo)\u003C/h5\u003E\u003Cul\u003E\u003Cli\u003EPublic to Private Repo such as \u003Ca href=\u0022https://www.sonatype.com/products/sonatype-nexus-repository\u0022 rel=\u0022noopener\u0022\u003ENexus\u003C/a\u003E. You can \u003Ca href=\u0022https://naiwaen.debuggingsoft.com/2025/09/step-download-npm-lib-via-curl-wget-and-manual-uplaod-to-nexus-thai/\u0022 rel=\u0022noreferrer noopener\u0022\u003Efollow the instruction to push Sheetjs tarball on this blog\u003C/a\u003E \u003C/li\u003E\u003C/ul\u003E\u003Ch5\u003E- Second Solution (Add tarball in Code Repository)\u003C/h5\u003E\u003Cul\u003E\u003Cli\u003EFirst, define the repository structure to determine where to place the tarball \u2014 in this case, SheetJS will be stored inside a \u003Cstrong\u003E\u003Ccode\u003Evendor\u003C/code\u003E\u003C/strong\u003E folder.\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Esimple-redmine-client/\n\u251c\u2500\u2500 vendor/\n\u2502 \u2514\u2500\u2500 xlsx-0.20.3.tgz\n\u251c\u2500\u2500 package.json\n\u251c\u2500\u2500 bun.lock\n\u251c\u2500\u2500 nuxt.config.ts\n\u2514\u2500\u2500 Dockerfile\u003C/pre\u003E\u003Cfigure\u003E\u003Cfigure\u003E\u003Cimg width=\u00221024\u0022 height=\u0022646\u0022 src=\u0022https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_package.webp?resize=1024%2C646\u0026amp;ssl=1\u0022 alt=\u0022\u0022 /\u003E\u003C/figure\u003E\u003Cfigure\u003E\u003Cimg width=\u00221024\u0022 height=\u0022628\u0022 src=\u0022https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_bunlock.webp?resize=1024%2C628\u0026amp;ssl=1\u0022 alt=\u0022\u0022 /\u003E\u003C/figure\u003E\u003C/figure\u003E\u003Cul\u003E\u003Cli\u003ERemove old xlsx package \u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Ebun remove xlsx\u003C/pre\u003E\u003Cul\u003E\u003Cli\u003EInstall Package from Vendor Folder\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003E# Download\ncurl -L -o vendor/xlsx-0.20.3.tgz https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz\n# Install\nbun add ./vendor/xlsx-0.20.3.tgz\u003C/pre\u003E\u003Cblockquote\u003E\u003Cp\u003ENote: If you do not run bun remove first, it will cause a dependency exception when installing the package.\u003C/p\u003E\u003C/blockquote\u003E\u003Cp\u003ENext, update the code \u2014 if the existing code still uses \u003Ccode\u003Erequire\u003C/code\u003E, refactor it to use a \u003Cstrong\u003Enamespace import\u003C/strong\u003E instead.\u003C/p\u003E\u003Cul\u003E\u003Cli\u003EOld Code\u003C/li\u003E\u003C/ul\u003E\u003Cul\u003E\u003C/ul\u003E\u003Cpre\u003Eimport XLSX from 'xlsx'\nconst XLSX = require('xlsx')\nconst wb = XLSX.readFile('data.xlsx')\n\n---\nimport XLSX from 'xlsx' // \u0026lt;-- default import\nconst wb = XLSX.read(buf, { type: 'buffer' })\u003C/pre\u003E\u003Cul\u003E\u003Cli\u003EImprove Code\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Eimport * as XLSX from 'xlsx' // 0.20.3 namespace import auto resolve ESM\u003C/pre\u003E\u003Cblockquote\u003E\u003Cp\u003EIf you have legacy codepages and need to read \u003Cstrong\u003EWindows-874 (TIS-620)\u003C/strong\u003E files, you'll need to include \u003Cstrong\u003E\u003Ccode\u003Ecpexcel\u003C/code\u003E \u003C/strong\u003Eas well \u2014 just follow the steps in the code below.\u003C/p\u003E\u003C/blockquote\u003E\u003Cpre\u003Eimport * as XLSX from 'xlsx'\nimport * as cptable from 'xlsx/dist/cpexcel.full.mjs'\nXLSX.set_cptable(cptable)\n\n// \u0e44\u0e1f\u0e25\u0e4c CSV \u0e17\u0e35\u0e48 export \u0e08\u0e32\u0e01\u0e23\u0e30\u0e1a\u0e1a\u0e40\u0e01\u0e48\u0e32/Excel \u0e1a\u0e19 Windows \u0e44\u0e17\u0e22 \u2192 \u0e21\u0e31\u0e01\u0e40\u0e1b\u0e47\u0e19 CP874 \u0e44\u0e21\u0e48\u0e21\u0e35 BOM\nconst wb = XLSX.read(buf, { type: 'buffer', codepage: 874 })\u003C/pre\u003E\u003Cul\u003E\u003Cli\u003ETest with \u003Ccode\u003Ebun run build\u003C/code\u003E and Then run \u003Cstrong\u003Emanual test\u003C/strong\u003E to\u003Cstrong\u003E export the Excel file\u003C/strong\u003E and verify the output.\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Ebun run build\u003C/pre\u003E\u003Cp\u003EFor those using Container, you'll also need to \u003Cstrong\u003ECOPY\u003C/strong\u003E the tarball into the image during the \u003Cstrong\u003Ebuild\u003C/strong\u003E stage. You can spot the \u003Cstrong\u003Eaddition lines\u003C/strong\u003E by looking at the \u003Cstrong\u003Ehighlighted\u003C/strong\u003E sections.\u003C/p\u003E\u003Cpre\u003E# use the official Bun image\n# see all versions at https://hub.docker.com/r/oven/bun/tags\nFROM oven/bun:1.3 AS base\nWORKDIR /app\n\n# install dependencies into temp directory\n# this will cache them and speed up future builds\nFROM base AS install\nCOPY package.json bun.lock ./\nCOPY vendor ./vendor\nCOPY . .\nENV npm_config_optional=true\nENV npm_config_platform=linux\nENV npm_config_arch=x64\nRUN BUN_POSTINSTALL=enable bun install --frozen-lockfile\n\n# Copy project files into the image\n\n# [Optional] tests \u0026amp; build\n# Test stage\nFROM install AS test\nENV NODE_ENV=test\n# Run tests and generate a report\nRUN bun test --reporter=junit --reporter-outfile=test-results.xml\n\n# Build stage\nFROM install AS build\nENV NODE_ENV=production\nRUN bun run build\n\n# Copy production dependencies and source code into final image\nFROM oven/bun:1.3-alpine AS runtime\nWORKDIR /app\n\n# Copy necessary files from the 'install' stage to the 'runtime' stage\n# COPY --from=install /app/node_modules ./node_modules\nCOPY --from=build --chown=bun:bun /app/.output .\n\n# Set user and expose port\nUSER bun\nEXPOSE 3000/tcp\n\n# Run the app\nENTRYPOINT [ \u0022sh\u0022, \u0022-c\u0022, \u0022bun run /app/server/index.mjs\u0022 ]\u003C/pre\u003E\u003Ch4\u003EReference\u003C/h4\u003E\u003Cul\u003E\u003Cli\u003E\u003Cstrong\u003E\u003Ca href=\u0022https://cdn.sheetjs.com/\u0022 rel=\u0022noopener\u0022\u003Ehttps://cdn.sheetjs.com/\u003C/a\u003E\u003C/strong\u003E \u003C/li\u003E\u003C/ul\u003E\n\n","context":"https://naiwaen.debuggingsoft.com/wp-json/activitypub/1.0/posts/49758/context","contentMap":{"en":"\u003Ch2\u003EFixed Cannot find module /app/node_modules/xlsx/dist/cpexcel.js\u003C/h2\u003E\n\n\u003Cp\u003EToday I want to share a problem I encountered when integrating SheetJS with Nuxt specifically in cases without authentication, accessing the path directly works fine. But when the path requires \u003Cstrong\u003EServer-Side Authentication\u003C/strong\u003E, it throws the error below.\u003C/p\u003E\u003Cpre\u003ECannot find module '/app/node_modules/xlsx/dist/cpexcel.js' from '/app/server/chunks/build/index-64cha0zE.mjs'\u003C/pre\u003E\u003Ch4\u003EWhy\u003C/h4\u003E\u003Cul\u003E\u003Cli\u003ESheetJS was designed to separate the codepage table into an optional file in order to reduce bundle size.SheetJS was designed to separate the codepage table into an optional file in order to reduce bundle size. \u003C/li\u003E\u003Cli\u003EThe legacy version (0.18.x) still relies on a CJS build that loads cpexcel via a dynamic \u003Ccode\u003Erequire() \u003C/code\u003Ewrapped in a \u003Ccode\u003Etry/catch\u003C/code\u003E block. As a result, when Nitro bundles the server output using Rollup and node-file-trace, \u003Cstrong\u003ERollup treats\u003C/strong\u003E the dynamic require() inside the try/catch \u003Cstrong\u003Eas optional code and skips it\u003C/strong\u003E. so \u003Cstrong\u003E\u003Cem\u003Ecpexcel.js\u003C/em\u003E\u003C/strong\u003E never gets copied into \u003Ccode\u003E.output\u003C/code\u003E. At runtime, the path resolution is correct, but the file is simply not there because it was never included during the build.\u003C/li\u003E\u003C/ul\u003E\u003Ch4\u003ESolution\u003C/h4\u003E\u003Cp\u003EUpgrading the SheetJS library from 0.18.5 \u2192 0.20.3 has two approaches, but for versions after 18, SheetJS requires you to pull the package directly from \u003Cstrong\u003E\u003Ca href=\u0022https://cdn.sheetjs.com/\u0022 rel=\u0022noopener\u0022\u003Ehttps://cdn.sheetjs.com/\u003C/a\u003E\u003C/strong\u003E instead.\u003C/p\u003E\u003Ch5\u003E- First Solution (Public to Private Repo)\u003C/h5\u003E\u003Cul\u003E\u003Cli\u003EPublic to Private Repo such as \u003Ca href=\u0022https://www.sonatype.com/products/sonatype-nexus-repository\u0022 rel=\u0022noopener\u0022\u003ENexus\u003C/a\u003E. You can \u003Ca href=\u0022https://naiwaen.debuggingsoft.com/2025/09/step-download-npm-lib-via-curl-wget-and-manual-uplaod-to-nexus-thai/\u0022 rel=\u0022noreferrer noopener\u0022\u003Efollow the instruction to push Sheetjs tarball on this blog\u003C/a\u003E \u003C/li\u003E\u003C/ul\u003E\u003Ch5\u003E- Second Solution (Add tarball in Code Repository)\u003C/h5\u003E\u003Cul\u003E\u003Cli\u003EFirst, define the repository structure to determine where to place the tarball \u2014 in this case, SheetJS will be stored inside a \u003Cstrong\u003E\u003Ccode\u003Evendor\u003C/code\u003E\u003C/strong\u003E folder.\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Esimple-redmine-client/\n\u251c\u2500\u2500 vendor/\n\u2502 \u2514\u2500\u2500 xlsx-0.20.3.tgz\n\u251c\u2500\u2500 package.json\n\u251c\u2500\u2500 bun.lock\n\u251c\u2500\u2500 nuxt.config.ts\n\u2514\u2500\u2500 Dockerfile\u003C/pre\u003E\u003Cfigure\u003E\u003Cfigure\u003E\u003Cimg width=\u00221024\u0022 height=\u0022646\u0022 src=\u0022https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_package.webp?resize=1024%2C646\u0026amp;ssl=1\u0022 alt=\u0022\u0022 /\u003E\u003C/figure\u003E\u003Cfigure\u003E\u003Cimg width=\u00221024\u0022 height=\u0022628\u0022 src=\u0022https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_bunlock.webp?resize=1024%2C628\u0026amp;ssl=1\u0022 alt=\u0022\u0022 /\u003E\u003C/figure\u003E\u003C/figure\u003E\u003Cul\u003E\u003Cli\u003ERemove old xlsx package \u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Ebun remove xlsx\u003C/pre\u003E\u003Cul\u003E\u003Cli\u003EInstall Package from Vendor Folder\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003E# Download\ncurl -L -o vendor/xlsx-0.20.3.tgz https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz\n# Install\nbun add ./vendor/xlsx-0.20.3.tgz\u003C/pre\u003E\u003Cblockquote\u003E\u003Cp\u003ENote: If you do not run bun remove first, it will cause a dependency exception when installing the package.\u003C/p\u003E\u003C/blockquote\u003E\u003Cp\u003ENext, update the code \u2014 if the existing code still uses \u003Ccode\u003Erequire\u003C/code\u003E, refactor it to use a \u003Cstrong\u003Enamespace import\u003C/strong\u003E instead.\u003C/p\u003E\u003Cul\u003E\u003Cli\u003EOld Code\u003C/li\u003E\u003C/ul\u003E\u003Cul\u003E\u003C/ul\u003E\u003Cpre\u003Eimport XLSX from 'xlsx'\nconst XLSX = require('xlsx')\nconst wb = XLSX.readFile('data.xlsx')\n\n---\nimport XLSX from 'xlsx' // \u0026lt;-- default import\nconst wb = XLSX.read(buf, { type: 'buffer' })\u003C/pre\u003E\u003Cul\u003E\u003Cli\u003EImprove Code\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Eimport * as XLSX from 'xlsx' // 0.20.3 namespace import auto resolve ESM\u003C/pre\u003E\u003Cblockquote\u003E\u003Cp\u003EIf you have legacy codepages and need to read \u003Cstrong\u003EWindows-874 (TIS-620)\u003C/strong\u003E files, you'll need to include \u003Cstrong\u003E\u003Ccode\u003Ecpexcel\u003C/code\u003E \u003C/strong\u003Eas well \u2014 just follow the steps in the code below.\u003C/p\u003E\u003C/blockquote\u003E\u003Cpre\u003Eimport * as XLSX from 'xlsx'\nimport * as cptable from 'xlsx/dist/cpexcel.full.mjs'\nXLSX.set_cptable(cptable)\n\n// \u0e44\u0e1f\u0e25\u0e4c CSV \u0e17\u0e35\u0e48 export \u0e08\u0e32\u0e01\u0e23\u0e30\u0e1a\u0e1a\u0e40\u0e01\u0e48\u0e32/Excel \u0e1a\u0e19 Windows \u0e44\u0e17\u0e22 \u2192 \u0e21\u0e31\u0e01\u0e40\u0e1b\u0e47\u0e19 CP874 \u0e44\u0e21\u0e48\u0e21\u0e35 BOM\nconst wb = XLSX.read(buf, { type: 'buffer', codepage: 874 })\u003C/pre\u003E\u003Cul\u003E\u003Cli\u003ETest with \u003Ccode\u003Ebun run build\u003C/code\u003E and Then run \u003Cstrong\u003Emanual test\u003C/strong\u003E to\u003Cstrong\u003E export the Excel file\u003C/strong\u003E and verify the output.\u003C/li\u003E\u003C/ul\u003E\u003Cpre\u003Ebun run build\u003C/pre\u003E\u003Cp\u003EFor those using Container, you'll also need to \u003Cstrong\u003ECOPY\u003C/strong\u003E the tarball into the image during the \u003Cstrong\u003Ebuild\u003C/strong\u003E stage. You can spot the \u003Cstrong\u003Eaddition lines\u003C/strong\u003E by looking at the \u003Cstrong\u003Ehighlighted\u003C/strong\u003E sections.\u003C/p\u003E\u003Cpre\u003E# use the official Bun image\n# see all versions at https://hub.docker.com/r/oven/bun/tags\nFROM oven/bun:1.3 AS base\nWORKDIR /app\n\n# install dependencies into temp directory\n# this will cache them and speed up future builds\nFROM base AS install\nCOPY package.json bun.lock ./\nCOPY vendor ./vendor\nCOPY . .\nENV npm_config_optional=true\nENV npm_config_platform=linux\nENV npm_config_arch=x64\nRUN BUN_POSTINSTALL=enable bun install --frozen-lockfile\n\n# Copy project files into the image\n\n# [Optional] tests \u0026amp; build\n# Test stage\nFROM install AS test\nENV NODE_ENV=test\n# Run tests and generate a report\nRUN bun test --reporter=junit --reporter-outfile=test-results.xml\n\n# Build stage\nFROM install AS build\nENV NODE_ENV=production\nRUN bun run build\n\n# Copy production dependencies and source code into final image\nFROM oven/bun:1.3-alpine AS runtime\nWORKDIR /app\n\n# Copy necessary files from the 'install' stage to the 'runtime' stage\n# COPY --from=install /app/node_modules ./node_modules\nCOPY --from=build --chown=bun:bun /app/.output .\n\n# Set user and expose port\nUSER bun\nEXPOSE 3000/tcp\n\n# Run the app\nENTRYPOINT [ \u0022sh\u0022, \u0022-c\u0022, \u0022bun run /app/server/index.mjs\u0022 ]\u003C/pre\u003E\u003Ch4\u003EReference\u003C/h4\u003E\u003Cul\u003E\u003Cli\u003E\u003Cstrong\u003E\u003Ca href=\u0022https://cdn.sheetjs.com/\u0022 rel=\u0022noopener\u0022\u003Ehttps://cdn.sheetjs.com/\u003C/a\u003E\u003C/strong\u003E \u003C/li\u003E\u003C/ul\u003E\n\n"},"icon":{"type":"Image","url":"https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_cover.webp?resize=150%2C150\u0026ssl=1","mediaType":"image/webp"},"image":{"type":"Image","url":"https://i0.wp.com/naiwaen.debuggingsoft.com/blog/wp-content/uploads/2026/08/sheetjs_error_cpexcel_cover.webp?fit=1024%2C585\u0026ssl=1","mediaType":"image/webp"},"published":"2026-08-07T10:31:02Z","tag":[],"url":"https://naiwaen.debuggingsoft.com/2026/08/fixed-cannot-find-module-app-node_modules-xlsx-dist-cpexcel-js/","to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://naiwaen.debuggingsoft.com/wp-json/activitypub/1.0/actors/1/followers"],"mediaType":"text/html","replies":{"id":"https://naiwaen.debuggingsoft.com/wp-json/activitypub/1.0/posts/49758/replies","type":"Collection","first":{"id":"https://naiwaen.debuggingsoft.com/wp-json/activitypub/1.0/posts/49758/replies?page=1","type":"CollectionPage","partOf":"https://naiwaen.debuggingsoft.com/wp-json/activitypub/1.0/posts/49758/replies","items":[]}},"likes":{"id":"https://naiwaen.debuggingsoft.com/wp-json/activitypub/1.0/posts/49758/likes","type":"Collection","totalItems":0},"shares":{"id":"https://naiwaen.debuggingsoft.com/wp-json/activitypub/1.0/posts/49758/shares","type":"Collection","totalItems":0},"interactionPolicy":{"canAnnounce":{"automaticApproval":"https://www.w3.org/ns/activitystreams#Public","always":"https://www.w3.org/ns/activitystreams#Public"},"canLike":{"automaticApproval":"https://www.w3.org/ns/activitystreams#Public","always":"https://www.w3.org/ns/activitystreams#Public"},"canQuote":{"automaticApproval":"https://www.w3.org/ns/activitystreams#Public","always":"https://www.w3.org/ns/activitystreams#Public"},"canReply":{"automaticApproval":"https://www.w3.org/ns/activitystreams#Public","always":"https://www.w3.org/ns/activitystreams#Public"}}}