Draft
[WIP] Build static-first visual CMS with real-time collaboration#1
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.
Original prompt
You are a senior distributed systems architect and full-stack engineer.
You are building a 10-year durable, static-first visual CMS with real-time collaboration.
You must follow the architectural constraints strictly. Do not introduce unnecessary frameworks or dynamic runtime dependencies.
🎯 Objective
Build a static-first, Git-canonical visual page builder with:
Hugo static output
JSON Page Graph canonical format
Git as the only source of truth
Media stored in R2/S3
React used only for the builder canvas
HTMX or server-rendered admin UI
Yjs CRDT for real-time collaboration
Cloudflare Durable Objects for collaboration relay
Zero runtime CMS in production
Deterministic Git diffs
Schema validation
Long-term replaceability
🚨 Architectural Rules (Non-Negotiable)
Production site must be 100% static HTML (Hugo + CDN).
No runtime CMS API calls allowed in production.
Git is canonical storage.
CRDT state is ephemeral and rebuildable from Git.
Page content stored as structured JSON (no raw HTML blobs).
React used only for canvas/editor, not entire admin app.
Collaboration layer must use Yjs.
WebSocket relay must use Cloudflare Durable Objects.
Media must be uploaded directly to R2 via signed URLs.
All content must validate against a JSON Schema.
All builder operations must be atomic Yjs transactions.
No Redis. No Kubernetes. No unnecessary infra.
Do not violate these rules.
🏗 System Components to Implement
You must implement:
Create:
forge.pagegraph.v1
JSON Schema validation
Migration placeholder system
Deterministic serialization rules
React-based canvas that:
Renders page graph visually
Allows drag-and-drop sections
Allows nested components
Uses Tiptap for rich text
Uses Yjs binding for CRDT
Implements atomic transactions
Serializes to PageGraph JSON
Supports Save Draft and Publish
Do not use large SPA frameworks for the entire app.
Implement:
Yjs document structure
Durable Object class
WebSocket handling
Snapshot + replay mechanism
Awareness (presence)
Tombstone cache for deletes
Soft-lock UI indicators
Ensure:
One Durable Object per page
CRDT state never canonical
Snapshots every N updates
Implement:
GitHub App authentication
Branch-based draft workflow
Commit deterministic JSON
PR-based publish flow
CI-triggered static builds
Implement:
Recursive node rendering
Block dispatch system
CSS emission strategy
No runtime dependencies
Pure static HTML output
Implement:
Signed upload URLs
Immutable hash-based filenames
Direct-to-R2 upload
URL reference in PageGraph
Implement using HTMX or server-rendered pages:
Site list
Page list
Build logs
Settings
User roles
React must NOT be required for these pages.
🧠 CRDT Document Model
Use:
Y.Map("nodes")
Y.Map("styles")
Y.Map("assets")
Y.Map("richtext")
Y.Map("meta")
All builder operations must be wrapped in:
doc.transact(() => {
// operation
})
Define transaction patterns for:
Add node
Move node
Delete node
Edit prop
Edit rich text
Apply style
Conflict rules:
Character-level merge for text
Deterministic structural merge
Soft-lock awareness for UI only
🔒 Durability Requirements
System must survive:
Framework changes
Collaboration layer replacement
Hosting migration
Git provider migration
Editor rewrite
PageGraph JSON must remain usable without editor.
📦 Deliverables
Generate:
Folder structure
Cloudflare Worker + Durable Object code
Yjs integration code
React canvas builder skeleton
JSON Schema file
Hugo renderer templates
GitHub Actions build pipeline
R2 signed upload endpoint
Minimal HTMX admin pages
README explaining architecture
Generate in incremental phases:
Phase 1 – PageGraph + Hugo rendering
Phase 2 – Builder without collaboration
Phase 3 – Yjs integration
Phase 4 – Durable Objects relay
Phase 5 – Git integration
Phase 6 – Media upload
Phase 7 – Admin shell
Do not skip phases.
🚫 Forbidden Behaviors
Do NOT:
Introduce a runtime database for canonical content.
Store content outside Git.
Use Next.js for entire admin system.
Add GraphQL.
Add unnecessary abstractions.
Store raw HTML as canonical format.
Introduce server-side rendering for production site.
Add Redis or Kubernetes.
Make CRDT state canonical.
🧠 Code Quality Standards
TypeScript required.
Strict typing.
Clear separation of concerns.
No magic.
Small dependencies.
Well-commented.
Deterministic serialization.
Clear transaction boundaries.
Migration-ready schema.
🏁 Output Format
Provide production-ready code.
Use explicit file paths.
Explain architecture decisions briefly.
Keep everything modular.
Make it deployable.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.