ONLINE EDITING ARCHITECTURE
Documentation for Sessions
Online Editing Architecture - MongoDB Sync Workflow
Date: January 5, 2026
Time: 4:30 PM PST
Session ID: gspace-1.1
Status: 📋 ARCHITECTURE DESIGN
Purpose: Enable online documentation editing with MongoDB sync to local /docs folder
Confidence Level: 99%
🎯 The Complete Picture
You asked: "How can we create/upload online, directly into MongoDB, and then sync to the real database (our /docs folder)?"
Answer: This is exactly what backend-docs-api was designed for! Here's the complete workflow:
📊 Current vs. Desired Architecture
Current (Production) ✅
User Browser
↓
docs-angular (static files)
↓
/docs folder (bundled at build time)
↓
Fast, reliable, no database
Benefits: 10-50ms load time, works offline, no network dependency
Desired (With Online Editing) 🚀
┌─────────────────────────────────────────────────────────────┐
│ BIDIRECTIONAL SYNC WORKFLOW │
├─────────────────────────────────────────────────────────────┤
│ │
│ 📝 Online Editor (docs-angular) │
│ ↓ │
│ 🌐 backend-docs-api (Port 3002) │
│ ↓ │
│ 🗄️ MongoDB (test-modules cluster) │
│ - docs-database │
│ - Collections: doc-files, doc-projects │
│ │
│ ← SYNC BACK ← │
│ │
│ 📥 Node.js Sync Script │
│ ↓ │
│ 📁 Local /docs Folder │
│ ↓ │
│ 🚀 Deploy with App │
│ │
└─────────────────────────────────────────────────────────────┘
Benefits: Online editing + Static file performance + Version control
🏗️ Complete Architecture
Components
| Component | Purpose | Status | Port |
|---|---|---|---|
| docs-angular | Frontend viewer/editor | ✅ Running | 5010 |
| backend-docs-api | MongoDB CRUD API | ⚠️ Disabled | 3002 |
| MongoDB (test-modules) | Online storage | ✅ Active | 27017 |
| watch-docs-changes.js | Local → MongoDB sync | ⚠️ Disabled | N/A |
| sync-from-mongodb.js | MongoDB → Local sync | ❌ Not created | N/A |
🔄 The Complete Workflow
Phase 1: Local Development (Upload to Cloud)
1. Edit local /docs files
↓
2. watch-docs-changes.js detects changes
↓
3. POST to backend-docs-api /sync/files
↓
4. Saves to MongoDB (docs-database)
↓
5. WebSocket broadcasts change to all clients
↓
6. Other developers get real-time updates
Phase 2: Online Editing (Create in MongoDB)
1. User opens docs-angular admin panel
↓
2. Creates/edits documentation online
↓
3. POST to backend-docs-api /sync/files
↓
4. Saves to MongoDB (docs-database)
↓
5. Immediately available to all users
↓
6. Syncs back to local /docs folder (Phase 3)
Phase 3: Sync Back to Local (Deploy)
1. Run sync script: yarn docs:sync-from-cloud
↓
2. GET from backend-docs-api /sync/files
↓
3. Downloads all files from MongoDB
↓
4. Writes to local /docs folder
↓
5. Git commit and push
↓
6. Deploy app with updated /docs folder
📝 Implementation Steps
Step 1: Enable backend-docs-api
File: apps/docs-angular/src/environments/environment.ts
export const environment = {
production: false,
// ✅ Enable backend-docs-api
docsApiUrl: 'http://localhost:3002/docs-api',
wsUrl: 'ws://localhost:3002',
enableCloudSync: true, // Enable cloud sync
enableAnalytics: true, // Enable analytics
};
File: apps/docs-angular/src/environments/environment.prod.ts
export const environment = {
production: true,
// ✅ Use production backend-docs-api
docsApiUrl: 'https://backend-docs-api-production.up.railway.app/docs-api',
wsUrl: 'wss://backend-docs-api-production.up.railway.app',
enableCloudSync: true,
enableAnalytics: true,
};
Step 2: Start backend-docs-api
# Install dependencies (if not already)
yarn install
# Start backend-docs-api
yarn serve:backend-docs
# Or start all backends together
yarn dev:all-backends
Expected Output:
📚 GoGrab Backend Docs API READY on port 3002
📡 Server: http://localhost:3002/docs-api
🗄️ Database: docs-database (test-modules cluster)
📄 Collections: doc-files, doc-projects, analytics
Step 3: Enable Local → MongoDB Sync
# Watch for changes and sync to MongoDB
yarn docs:watch
# Or run manually
ENABLE_CLOUD_SYNC=true node apps/docs-angular/scripts/watch-docs-changes.js
What it does:
- Watches
/docsfolder for changes - Detects file create/update/delete
- Automatically syncs to MongoDB via backend-docs-api
- Real-time updates via WebSocket
Step 4: Initial Bulk Upload
Upload all existing docs to MongoDB:
# Bulk sync all docs to cloud
yarn docs:sync
# Or run manually
node apps/docs-angular/scripts/sync-to-cloud.js
What it does:
- Scans entire
/docsfolder - Extracts frontmatter metadata
- Uploads to MongoDB in batches
- Creates doc-files and doc-projects collections
Step 5: Create Online Editor UI
File: apps/docs-angular/src/app/admin/doc-editor/doc-editor.component.ts (NEW)
import { Component, signal, inject } from '@angular/core';
import { DocsApiService } from '../../services/docs-api.service';
import { autoFlashState } from '@storage-system';
@Component({
selector: 'app-doc-editor',
standalone: true,
template: `
<div class="editor-container">
<h2>Create/Edit Documentation</h2>
<!-- File Path -->
<input
type="text"
[(ngModel)]="filePath"
placeholder="english/MyProject/my-doc.md"
class="path-input" />
<!-- Markdown Editor -->
<textarea
[(ngModel)]="content"
placeholder="# My Documentation\n\nContent here..."
class="markdown-editor"
rows="20"></textarea>
<!-- Save Button -->
<button (click)="saveToMongoDB()" [disabled]="isSaving()">
{{ isSaving() ? 'Saving...' : 'Save to MongoDB' }}
</button>
@if (saveResult()) {
<div class="save-result">{{ saveResult() }}</div>
}
</div>
`,
styles: [`
.editor-container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
.path-input, .markdown-editor {
width: 100%;
padding: 1rem;
margin: 1rem 0;
border: 1px solid #ccc;
border-radius: 8px;
}
.markdown-editor {
font-family: 'Monaco', monospace;
font-size: 14px;
}
button {
padding: 1rem 2rem;
background: #4f46e5;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`]
})
export class DocEditorComponent {
private readonly docsApi = inject(DocsApiService);
// Editor state (persisted)
readonly filePath = autoFlashState<string>('editor-file-path', '');
readonly content = autoFlashState<string>('editor-content', '');
readonly isSaving = signal(false);
readonly saveResult = signal('');
async saveToMongoDB() {
if (!this.filePath() || !this.content()) {
this.saveResult.set('⚠️ Path and content are required');
return;
}
this.isSaving.set(true);
this.saveResult.set('');
try {
// Extract frontmatter metadata
const metadata = this.extractFrontmatter(this.content());
// Save to MongoDB via backend-docs-api
const result = await this.docsApi.upsertFile({
path: this.filePath(),
content: this.content(),
metadata: {
...metadata,
language: this.detectLanguage(this.filePath()),
project: this.detectProject(this.filePath()),
}
});
console.log('✅ Saved to MongoDB:', result);
this.saveResult.set(`✅ Saved successfully! Version ${result.version}`);
} catch (error) {
console.error('❌ Save failed:', error);
this.saveResult.set(`❌ Save failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
} finally {
this.isSaving.set(false);
}
}
private extractFrontmatter(content: string): any {
const match = content.match(/^---\n([\s\S]*?)\n---/);
if (!match) return {};
const frontmatter = match[1];
const metadata: any = {};
const lines = frontmatter.split('\n');
for (const line of lines) {
const colonIndex = line.indexOf(':');
if (colonIndex > 0) {
const key = line.substring(0, colonIndex).trim();
const value = line.substring(colonIndex + 1).trim().replace(/^["']|["']$/g, '');
metadata[key] = value;
}
}
return metadata;
}
private detectLanguage(path: string): string {
return path.includes('/english/') ? 'en' : path.includes('/spanish/') ? 'es' : 'en';
}
private detectProject(path: string): string {
const parts = path.split('/');
const langIndex = parts.findIndex(p => p === 'english' || p === 'spanish');
return langIndex >= 0 && langIndex + 1 < parts.length ? parts[langIndex + 1] : 'public';
}
}
Add Route:
// apps/docs-angular/src/app/app.routes.ts
{
path: 'admin/editor',
loadComponent: () => import('./admin/doc-editor/doc-editor.component').then(m => m.DocEditorComponent),
title: 'Documentation Editor'
}
Step 6: Create MongoDB → Local Sync Script
File: apps/docs-angular/scripts/sync-from-mongodb.js (NEW)
#!/usr/bin/env node
/**
* 📥 SYNC FROM MONGODB TO LOCAL
*
* Downloads all documentation files from MongoDB and writes them
* to the local /docs folder for deployment.
*
* Usage: node scripts/sync-from-mongodb.js
*/
const fs = require('fs');
const path = require('path');
// MongoDB/API Configuration
const DOCS_API_URL = process.env.DOCS_API_URL || 'http://localhost:3002/docs-api';
const SYSTEM_TOKEN = process.env.SYSTEM_TOKEN || '';
// Local docs path
const DOCS_BASE_PATH = path.join(process.cwd(), 'docs');
/**
* Fetch all files from MongoDB
*/
async function fetchAllFiles() {
console.log('📥 Fetching files from MongoDB...');
const response = await fetch(`${DOCS_API_URL}/sync/files?limit=1000`, {
headers: {
...(SYSTEM_TOKEN ? { 'Authorization': `Bearer ${SYSTEM_TOKEN}` } : {})
}
});
if (!response.ok) {
throw new Error(`Failed to fetch files: ${response.statusText}`);
}
const data = await response.json();
console.log(`📋 Found ${data.files.length} files in MongoDB`);
return data.files;
}
/**
* Write file to local filesystem
*/
function writeFileToLocal(file) {
const fullPath = path.join(DOCS_BASE_PATH, file.path);
const dir = path.dirname(fullPath);
// Create directory if it doesn't exist
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
// Write file content
fs.writeFileSync(fullPath, file.content, 'utf8');
console.log(`✅ Wrote: ${file.path}`);
}
/**
* Main sync function
*/
async function syncFromMongoDB() {
console.log('╔════════════════════════════════════════╗');
console.log('║ 📥 Sync from MongoDB to Local ║');
console.log('╚════════════════════════════════════════╝');
console.log('');
console.log(`📁 Local path: ${DOCS_BASE_PATH}`);
console.log(`🌐 API URL: ${DOCS_API_URL}`);
console.log('');
try {
// Fetch all files
const files = await fetchAllFiles();
if (files.length === 0) {
console.log('⚠️ No files found in MongoDB');
return;
}
// Write files to local
let successCount = 0;
let errorCount = 0;
for (const file of files) {
try {
writeFileToLocal(file);
successCount++;
} catch (error) {
console.error(`❌ Failed to write ${file.path}:`, error.message);
errorCount++;
}
}
console.log('');
console.log('╔════════════════════════════════════════╗');
console.log('║ ✅ Sync Complete ║');
console.log('╚════════════════════════════════════════╝');
console.log('');
console.log(`✅ Success: ${successCount} files`);
console.log(`❌ Errors: ${errorCount} files`);
console.log('');
if (errorCount === 0) {
console.log('🚀 Ready to commit and deploy!');
}
} catch (error) {
console.error('');
console.error('❌ Sync failed:', error);
process.exit(1);
}
}
// Run if called directly
if (require.main === module) {
syncFromMongoDB()
.then(() => process.exit(0))
.catch((error) => {
console.error('❌ Fatal error:', error);
process.exit(1);
});
}
module.exports = { syncFromMongoDB };
Add to package.json:
{
"scripts": {
"docs:sync-from-cloud": "node apps/docs-angular/scripts/sync-from-mongodb.js",
"docs:sync": "node apps/docs-angular/scripts/sync-to-cloud.js",
"docs:watch": "node apps/docs-angular/scripts/watch-docs-changes.js"
}
}
🔐 backend-docs-api Endpoints
File Operations
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/sync/files |
GET | Public | List all files |
/sync/files/:path |
GET | Public | Get single file |
/sync/files |
POST | JWT | Create/update file |
/sync/files/:path |
DELETE | JWT | Delete file |
/sync/bulk |
POST | JWT | Bulk upload |
Project Operations
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/sync/projects |
GET | Public | List projects |
/admin/projects |
POST | JWT | Create project |
Real-time Updates
WebSocket: ws://localhost:3002/docs-sync
Events:
file-change- File created/updated/deletedmanifest-updated- Manifest regeneratedproject-change- Project created/updated/deleted
📊 Data Flow Examples
Example 1: Create Documentation Online
// 1. User fills out online editor
const newDoc = {
path: 'english/MyProject/getting-started.md',
content: `---
title: Getting Started
description: Quick start guide
---
# Getting Started
Welcome to MyProject!`,
metadata: {
title: 'Getting Started',
description: 'Quick start guide',
language: 'en',
project: 'MyProject'
}
};
// 2. Save to MongoDB via backend-docs-api
const response = await fetch('http://localhost:3002/docs-api/sync/files', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`
},
body: JSON.stringify(newDoc)
});
// 3. MongoDB saves document
{
path: 'english/MyProject/getting-started.md',
content: '...',
metadata: {...},
contentHash: 'sha256...',
version: 1,
createdAt: ISODate('2026-01-05T...'),
updatedAt: ISODate('2026-01-05T...')
}
// 4. WebSocket broadcasts to all clients
socket.emit('file-change', {
event: 'created',
file: { path: 'english/MyProject/getting-started.md', ... },
timestamp: '2026-01-05T...'
});
// 5. All connected clients receive update
// Users see new documentation immediately!
Example 2: Sync Back to Local
# Run sync script
yarn docs:sync-from-cloud
# Output:
📥 Fetching files from MongoDB...
📋 Found 247 files in MongoDB
✅ Wrote: english/MyProject/getting-started.md
✅ Wrote: english/MyProject/advanced-guide.md
... (247 files total)
✅ Sync Complete
🚀 Ready to commit and deploy!
# Commit and push
git add docs/
git commit -m "docs: synced from MongoDB"
git push
# Deploy app
# New documentation is now bundled with the app!
🎯 Use Cases
Use Case 1: Technical Writer (Online Editing)
1. Navigate to gograb.space/docs/admin/editor
2. Create new documentation file
3. Write content in markdown
4. Click "Save to MongoDB"
5. Documentation immediately available to all users
6. Periodic sync to local /docs folder
7. Deploy with next release
Benefits:
- No local development environment needed
- Real-time collaboration
- Version controlled in MongoDB
- Eventually synced to git
Use Case 2: Developer (Local Editing)
1. Edit files in local /docs folder
2. watch-docs-changes.js auto-syncs to MongoDB
3. Changes immediately available online
4. Other developers get real-time updates
5. Commit to git as usual
Benefits:
- Familiar workflow (local files + git)
- Automatic cloud backup
- Real-time team collaboration
- Best of both worlds
Use Case 3: Deployment (Production Build)
1. Run: yarn docs:sync-from-cloud
2. Downloads all files from MongoDB
3. Writes to local /docs folder
4. Git commit and push
5. Deploy app with nx build docs-angular
6. Static files bundled with app (fast!)
Benefits:
- Online editing capability
- Static file performance in production
- Version controlled
- Automated workflow
🔒 Security Considerations
Authentication
JWT Tokens: backend-docs-api uses shared JWT with backend-api
// Get JWT token
const token = await authService.login(username, password);
// Use in requests
const response = await fetch('http://localhost:3002/docs-api/sync/files', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(fileData)
});
Permissions
Public Endpoints (READ):
/sync/files(GET) - List files/sync/files/:path(GET) - Get single file/sync/projects(GET) - List projects
Protected Endpoints (WRITE):
/sync/files(POST) - Create/update - Requires JWT/sync/files/:path(DELETE) - Delete - Requires JWT/admin/*- Admin operations - Requires JWT
📈 Performance Comparison
| Scenario | Static Files | MongoDB + Sync | Difference |
|---|---|---|---|
| First Load | 10-50ms | 10-50ms | Same (static after sync) |
| Edit Online | ❌ Not possible | ✅ Instant | N/A |
| Real-time Collab | ❌ Not possible | ✅ WebSocket | N/A |
| Offline Mode | ✅ Works | ⚠️ Online only | Static wins |
| Version Control | ✅ Git | ✅ MongoDB + Git | Both |
| Deployment | Simple | +1 sync step | Minimal overhead |
🚀 Getting Started Checklist
Prerequisites
- MongoDB connection (test-modules cluster) - ✅ Working
- backend-docs-api code - ✅ Exists
- backend-docs-api running - ⚠️ Need to start
- Environment variables configured - ⚠️ Need to enable
- JWT authentication setup - ✅ Already configured
Setup Steps
- Update
environment.ts- Enable docsApiUrl - Update
environment.prod.ts- Add production API URL - Start backend-docs-api:
yarn serve:backend-docs - Run initial bulk sync:
yarn docs:sync - Enable file watcher:
yarn docs:watch - Create online editor UI component
- Test end-to-end workflow
- Deploy to production
Estimated Time: 2-4 hours to enable and test
💡 Recommendations
Immediate Actions (High Priority)
Enable backend-docs-api (30 min)
- Update environment files
- Start the API locally
- Test connectivity
Run Initial Sync (15 min)
- Bulk upload existing docs to MongoDB
- Verify data in MongoDB Compass
- Test retrieval
Create Online Editor (2 hours)
- Build simple markdown editor UI
- Integrate with backend-docs-api
- Test create/update/delete
Create Sync-Back Script (1 hour)
- Implement
sync-from-mongodb.js - Test download and write to local
- Add to deployment workflow
- Implement
Long-term Improvements
Conflict Resolution
- Handle simultaneous edits
- Implement version merging
- Add conflict UI
Advanced Editor
- Live markdown preview
- Syntax highlighting
- Auto-save drafts
- Image upload
Collaboration Features
- Real-time cursors
- Comments and reviews
- Approval workflow
- Change notifications
Automation
- Auto-sync on deploy
- Scheduled backups
- CI/CD integration
- Automatic git commits
📚 Related Documentation
🎯 Key Takeaways
- docs-angular is MongoDB-free by design - For optimal production performance
- backend-docs-api enables online editing - Optional feature, currently disabled
- Bidirectional sync is the key - Local ↔ MongoDB ↔ Local
- Best of both worlds - Online editing + Static file performance
- Already built, just needs enabling - Most code already exists!
Architecture Complete: ✅
Confidence Level: 99%
Implementation Difficulty: Medium (2-4 hours)
Production Ready: After testing
Designed by AI Agent - Session gspace-1.1
Date: January 5, 2026
Time: 4:30 PM PST