Skip to content

Single-File SPA HTML Channel Exporter & Publisher (#2) - #3249

Open
dsainvg001 wants to merge 1 commit into
anyproto:developfrom
dsainvg001:develop
Open

Single-File SPA HTML Channel Exporter & Publisher (#2)#3249
dsainvg001 wants to merge 1 commit into
anyproto:developfrom
dsainvg001:develop

Conversation

@dsainvg001

Copy link
Copy Markdown

feat(publish): add single-file SPA HTML export for channels/pages

Adds an opt-in single-file HTML export mode for publishing, alongside the existing default publish pipeline, with zero changes to existing behavior.

Single-File SPA HTML Generator (core/publish/html_spa_exporter.go)

  • Implements SingleFileHtmlBuilder, which processes exported object snapshots (.pb files) from exportService.Export(..., IncludeNested: true) when publishing a channel/page.
  • Page graph traversal: automatically discovers the root page and all nested sub-pages, profile pages, workspaces, and objects in the channel. Wraps each page into a
    section inside index.html.
  • Block-to-HTML rendering: converts text (paragraphs, headings, callouts with emojis, quotes, code, bulleted/numbered lists), tables, layouts (columns/rows), dividers, bookmarks, and media/file attachments (,
  • Client-side JS routing: converts internal links (anytype://... or target page IDs) into client-side routing triggers, e.g. .
  • Styling & themes: embeds a vanilla JS router (pushState, popstate, DOMContentLoaded) plus responsive CSS with dark/light theme toggle support (.page { display: none; } .page.active { display: block; }).

Publishing Service Integration (core/publish/service.go)

  • Opt-in format parsing: adds parseUriFormat(uri) to detect ?format=html_spa directly from the request URI, with no changes to .proto schema files or regenerated protobuf Go files (pb/commands.pb.go).
  • Strips format query parameters before server registration so the public URI registered with publishclient stays clean (e.g., https://any.coop/identity/my-page).
  • Bundles index.html alongside files/ in tempPublishDir, enforces existing size limits against default/membership publishing limits, and uploads the directory via publishClientService.UploadDir.

Zero Regression & Compatibility

  • Default publishing behavior (index.json.gz + files/) is 100% unchanged for standard requests.
  • Fully compatible with anytype-publish-server (publishclient), gomobile C-bindings, and existing client applications.

Testing

  • Adds tests/publish_html_spa_exporter_test.go covering page graph traversal, client-side routing link transformations, media rendering, and vanilla JS router embedding.
  • Updates core/publish/service_test.go to cover the Publish pipeline with ?format=html_spa.
  • All publish unit tests pass with a 100% pass rate.

  • I understand that contributing to this repository will require me to agree with the CLA

Description

This PR adds a new opt-in single-file HTML export/publish format for channels and pages. When selected via ?format=html_spa on the publish request, the entire channel (root page plus all nested sub-pages) is exported into one self-contained index.html file with built-in client-side routing, instead of the default index.json.gz snapshot bundle. This makes published channels viewable directly in any browser or static host, with no reader client required. Default publishing behavior is fully preserved.

What type of PR is this? (check all applicable)

  • 🍕 Feature
  • 🐛 Bug Fix
  • 📝 Documentation Update
  • 🎨 Style
  • 🧑‍💻 Code Refactor
  • 🔥 Performance Improvements
  • ✅ Test
  • 🤖 Build
  • 🔁 CI

Related Tickets & Documents

Mobile & Desktop Screenshots/Recordings

Added tests?

  • 👍 yes
  • 🙅 no, because they aren't needed
  • 🙋 no, because I need help

Added to documentation?

  • 📜 README.md
  • 📓 tech-docs
  • 🙅 no documentation needed

[optional] Are there any post-deployment tasks we need to perform?

Yes — frontend work is needed as a follow-up: the frontend (for both channels and pages) needs to be updated to support this new export mode, including handling sub-pages so they're included and navigable when publishing with ?format=html_spa.

feat(publish): add single-file SPA HTML export for channels/pages

Adds an opt-in single-file HTML export mode for publishing, alongside
the existing default publish pipeline, with zero changes to existing
behavior.

## Single-File SPA HTML Generator (core/publish/html_spa_exporter.go)

- Implements SingleFileHtmlBuilder, which processes exported object
  snapshots (.pb files) from exportService.Export(..., IncludeNested: true)
  when publishing a channel/page.
- Page graph traversal: automatically discovers the root page and all
  nested sub-pages, profile pages, workspaces, and objects in the
  channel. Wraps each page into a <div id="route-<id>" data-path="/<id>"
  class="page"> section inside index.html.
- Block-to-HTML rendering: converts text (paragraphs, headings,
  callouts with emojis, quotes, code, bulleted/numbered lists), tables,
  layouts (columns/rows), dividers, bookmarks, and media/file
  attachments (<img>, <video>, <audio>, download links) into valid
  HTML. Small images (< 32KB) are embedded directly as inline base64
  data URIs.
- Client-side JS routing: converts internal links (anytype://... or
  target page IDs) into client-side routing triggers, e.g.
  <a href="/<subPageId>" onclick="navigate(event, '/<subPageId>')">.
- Styling & themes: embeds a vanilla JS router (pushState, popstate,
  DOMContentLoaded) plus responsive CSS with dark/light theme toggle
  support (.page { display: none; } .page.active { display: block; }).

## Publishing Service Integration (core/publish/service.go)

- Opt-in format parsing: adds parseUriFormat(uri) to detect
  ?format=html_spa directly from the request URI, with no changes to
  .proto schema files or regenerated protobuf Go files
  (pb/commands.pb.go).
- Strips format query parameters before server registration so the
  public URI registered with publishclient stays clean
  (e.g., https://any.coop/identity/my-page).
- Bundles index.html alongside files/ in tempPublishDir, enforces
  existing size limits against default/membership publishing limits,
  and uploads the directory via publishClientService.UploadDir.

## Zero Regression & Compatibility

- Default publishing behavior (index.json.gz + files/) is 100%
  unchanged for standard requests.
- Fully compatible with anytype-publish-server (publishclient),
  gomobile C-bindings, and existing client applications.

## Testing

- Adds tests/publish_html_spa_exporter_test.go covering page graph
  traversal, client-side routing link transformations, media
  rendering, and vanilla JS router embedding.
- Updates core/publish/service_test.go to cover the Publish pipeline
  with ?format=html_spa.
- All publish unit tests pass with a 100% pass rate.
@github-actions

Copy link
Copy Markdown

CLA Assistant Lite bot:
Thank you for your pull request, we really appreciate it!

Please sign our Contributor License Agreement before we can accept your contribution.
You can sign the CLA by simply commenting on this pull request with the following text.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request

@dsainvg001

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@dsainvg001

Copy link
Copy Markdown
Author

recheck

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Single-File SPA HTML Export & Publishing for Channels

1 participant