Regenesys Creative OS Admin Workspace

Use the clean admin workspace to intake requests, review and edit creative, manage reusable assets, and keep the whole OS organised.

Not connected

Quick actions

The fastest ways to move work forward.

Intake
Paste an emailTurn a messy email into a brief and create a design request for the team.
Queue
Open requestsSee work by status, owner, due date and next action.
Approve
Review draftsSee outputs, approve them or send them back with changes.
Edit
Make changesChange titles, dates, copy or visual direction and regenerate.
Library
Bulk intake assetsScan and save logos, templates, brochures and references into the OS.
Templates
Promote template candidatesTurn approved reference designs into reusable template records.
Memory
Manage entitiesTeach the OS brands, events, schools and campaign identities.
Copy
Generate campaign copyCreate and regenerate on-brand marketing copy without leaving admin.

Workspace summary

Your live creative workload at a glance.

Needs your attention

The most urgent requests and the work waiting for your decision.

Live activity

Approvals, edits, draft generation and handoff events update here automatically.

Master Format Registry

Dimensions, safe zones, copy limits and layout behaviour for every asset type the OS can generate.

FormatCategoryCanvasCopy profileLayoutRules

Design request queue

Track design work by status, priority, due date, owner and approval stage.

DueRequestSchoolAssetPriorityStatusAssignedActions

Email to request

Paste an email or WhatsApp-style request. The OS will generate a brief and create the design request automatically.

Generated result

This becomes the request the design team will see.

No email processed yet.

Review request

See what the designer produced, then approve it or send back changes.

Latest draft & files

Open, download or export the current outputs.

Edit request

Change the brief, title, date, CTA or visual direction yourself.

Generate revised draft

Use the same generation engine without leaving admin.

No revised draft generated yet.

Asset downloads

Open, export, edit and delete request files, OS assets and generated concepts.

Upload to OS Library

Bulk upload logos, templates, brochures, banners, references and final assets. Edit scanner mistakes below.

Intake results

Review what the scanner suggested and what was saved.

OS Library assets

Edit entity assignment, asset type, role and status when the scanner gets it wrong.

Template mapper

Review candidate assets and promote the right ones into reusable templates.

Current templates

All templates already registered in the OS.

Entity Registry

Locked Regenesys entities with editable landing pages and clear workspace access.

Entity workspace

Select an entity to view logos, templates, PDFs, generated assets, requests and landing page.

Add Entity

Keep this compact. You can edit landing pages whenever URLs are confirmed.

AI copy generator

Create campaign copy using the same school, asset and template logic already stored in the OS.

Recent copy

Regenerate, review and reuse generated copy records.

Brochure Studio

Create brochure-ready programme packs, regenerate brochure copy, and export a clean PDF print view.

Saved brochure projects

Pick up an existing brochure pack or duplicate from a previous version.

Brochure preview

A print-friendly two-page brochure preview built from your saved fields and generated copy.

Version history

Track brochure regeneration and edit history.

Smart PDF Brochure Templates

Upload approved brochures or prospectuses as reusable PDF templates, map text changes with AI, and export a new edited PDF while preserving the original design.

1. Upload PDF as template

Use an existing MBA brochure, prospectus or programme PDF as the design base.

Saved PDF templates

Select a PDF template to reuse.

No PDF templates loaded yet.

2. Prompt changes

Tell the OS what to change. Example: “Change MBA to Bachelor of Business Administration, July 2026 to January 2027, and Apply Now to Enquire Now.”

How it works: the uploaded PDF stays as the design template. The OS covers selected old text and writes the new text over it. This is best for changing programme names, dates, prices, CTAs, module names and short paragraphs without redesigning the PDF.

Replacement map

Review AI-suggested changes before export.

PageFindReplace with
No replacements yet.

PDF preview

Preview the uploaded template. Text extraction is used for smart replacement mapping.

Page 0 / 0
Upload or select a PDF template to preview it here.

Export edited PDF

Generate a proper PDF download from the original template plus your approved replacement map.

Foundation data

The clean reference layer behind the OS.

Brand assets

Logos and approved brand files currently available to the OS.

System & backup

Check platform health, export backups and inspect configuration lists without leaving the dashboard.

Prompt settings

Read-only view of active AI prompt controls currently in the Worker.

Connect Worker

Paste the Worker API URL once, then load your admin workspace.

`; } function openBrochurePrintView(){ const project = brochureProjectById(state.selectedBrochureId); if(!project){ $('brochureMessage').innerHTML = '
Open or save a brochure project first.
'; return; } const popup = window.open('', '_blank', 'width=1100,height=900'); popup.document.open(); popup.document.write(brochurePrintHtml(project)); popup.document.close(); popup.focus(); setTimeout(() => popup.print(), 500); } function renderFoundation(){ if(!$('foundationCards')) return; $('foundationCards').innerHTML=`
Schools
${state.schools.length}
School records
Asset types
${state.assetTypes.length}
Marketing formats
Templates
${state.templates.length}
Reusable template records
Knowledge
${state.knowledgeSources.length}
Knowledge sources
`; $('foundationTables').innerHTML=`
Schools
The brands and schools the OS already recognises.
${state.schools.slice(0,20).map(s => `${e(s.official_name || s.id)} (${e(s.status || 'n/a')})`).join('
')}
Templates
Current template records.
${state.templates.slice(0,20).map(t => `${e(t.template_name || t.id)} · ${e(t.template_status || '')}`).join('
')}
Knowledge sources
Connected knowledge the OS can draw from.
${state.knowledgeSources.slice(0,20).map(k => `${e(k.source_name || '')} · ${e(k.source_type || '')} · ${e(k.status || '')}`).join('
')}
`; $('brandAssetList').innerHTML=state.brandAssets.length ? state.brandAssets.slice(0,40).map(b => `
${e(b.asset_name || '')}
${e(b.linked_school || '')} · ${e(b.asset_type || '')}
${badge(b.file_format)} ${badge(b.is_default ? 'default' : 'asset')}
${b.r2_key ? `` : ''}
`).join('') : '
No brand assets found.
'; } function renderSystem(){ if(!$('systemTables')) return; $('backupLink').href = api('/api/admin/backup'); $('systemTables').innerHTML=`
Platform settings
Read-only configuration values currently stored in the OS.
${state.platformSettings.slice(0,20).map(s => `${e(s.setting_name || s.setting_key)} · ${e(s.setting_category || '')}`).join('
')}
Feature flags
Current feature toggles.
${state.featureFlags.slice(0,20).map(f => `${e(f.flag_name || f.flag_key)} · ${f.is_enabled ? 'enabled' : 'disabled'}`).join('
')}
`; $('promptSettingsList').innerHTML=state.promptSettings.length ? state.promptSettings.slice(0,40).map(p => `
${e(p.setting_name || p.setting_key)}
${e(p.setting_category || '')}
${badge(p.is_active ? 'active' : 'inactive')}
${e((p.setting_value || '').slice(0,220))}
`).join('') : '
No prompt settings found.
'; } window.summaryNavigate = summaryNavigate; window.editRequestFromRow = editRequestFromRow; window.openReviewFromRow = openReviewFromRow; window.quickRequestStatus = quickRequestStatus; window.approveSelectedRequest = approveSelectedRequest; window.requestChangesForSelectedRequest = requestChangesForSelectedRequest; window.openSelectedInEditor = openSelectedInEditor; window.saveEditedRequest = saveEditedRequest; window.generateRevisionDraft = generateRevisionDraft; window.exportAssetAs = exportAssetAs; window.clearEmailForm = clearEmailForm; window.clearIntakeResults = clearIntakeResults; window.createTemplateFromAsset = createTemplateFromAsset; window.regenerateCopy = regenerateCopy; const pdfStudio = {templates: [], selectedTemplate: null, replacements: [], pdfBytes: null, pdfDocProxy: null, extractedText: [], page: 1, pageCount: 0}; function pdfMsg(id, html){ const el=$(id); if(el) el.innerHTML = html || ''; } function pdfTemplateListHtml(){ if(!pdfStudio.templates.length) return '
No PDF templates saved yet.
'; return pdfStudio.templates.map(t => `
${e(t.template_name || 'PDF template')}
${e(t.source_file_name || 'PDF')} · ${e(t.page_count || 0)} page${Number(t.page_count)===1?'':'s'}
${e(t.updated_at || '')}
`).join(''); } function renderPdfTemplates(){ if(!$('pdfTemplateList')) return; $('pdfTemplateList').innerHTML = pdfTemplateListHtml(); $('pdfTemplateList').querySelectorAll('.pdf-template-item').forEach(el => el.onclick = () => selectPdfTemplate(el.dataset.id)); } async function loadPdfTemplates(){ if(!$('pdfTemplateList') || !state.apiBase) return; try{ const result = await get('/api/brochure/pdf-templates?status=all'); pdfStudio.templates = result.templates || []; renderPdfTemplates(); }catch(err){ $('pdfTemplateList').innerHTML = `
${e(err.message)}
`; } } async function extractPdfTextFromArrayBuffer(arrayBuffer){ if(typeof pdfjsLib === 'undefined') throw new Error('PDF.js did not load. Check your internet connection or CDN access.'); const doc = await pdfjsLib.getDocument({data: arrayBuffer.slice(0)}).promise; const items = []; for(let p=1; p<=doc.numPages; p++){ const page = await doc.getPage(p); const viewport = page.getViewport({scale:1}); const content = await page.getTextContent(); for(let i=0; iChoose a PDF file first.'); return; } if(!state.apiBase){ pdfMsg('pdfUploadMessage','
Connect the Worker API first.
'); return; } try{ pdfMsg('pdfUploadMessage','
Reading PDF and extracting editable text positions…
'); const buf = await file.arrayBuffer(); const extracted = await extractPdfTextFromArrayBuffer(buf); const form = new FormData(); form.append('file', file, file.name); form.append('template_name', $('pdfTemplateName').value || file.name.replace(/\.pdf$/i,'')); form.append('school_id', $('pdfTemplateSchool').value || ''); form.append('template_notes', $('pdfTemplateNotes').value || ''); form.append('page_count', String(extracted.pageCount)); form.append('extracted_text_json', JSON.stringify(extracted.items)); form.append('editable_fields_json', JSON.stringify([])); const result = await postForm('/api/brochure/pdf-templates/upload', form); pdfMsg('pdfUploadMessage','
PDF template uploaded and captured.
'); await loadPdfTemplates(); if(result.template && result.template.id) await selectPdfTemplate(result.template.id); }catch(err){ pdfMsg('pdfUploadMessage',`
${e(err.message)}
`); } } async function selectPdfTemplate(id){ const tpl = pdfStudio.templates.find(t => t.id === id); if(!tpl) return; pdfStudio.selectedTemplate = tpl; pdfStudio.replacements = []; renderPdfTemplates(); renderPdfReplacements(); try{ pdfMsg('pdfProjectMessage','
Loading PDF template…
'); const response = await fetch(api('/api/brochure/pdf-templates/file?id=' + encodeURIComponent(id))); if(!response.ok) throw new Error('Could not load PDF template.'); pdfStudio.pdfBytes = await response.arrayBuffer(); const loaded = await extractPdfTextFromArrayBuffer(pdfStudio.pdfBytes); pdfStudio.pdfDocProxy = loaded.doc; pdfStudio.pageCount = loaded.pageCount; pdfStudio.page = 1; pdfStudio.extractedText = Array.isArray(tpl.extracted_text) && tpl.extracted_text.length ? tpl.extracted_text : loaded.items; await renderPdfPage(); pdfMsg('pdfProjectMessage','
Template loaded. Add prompt changes or manual replacements.
'); }catch(err){ pdfMsg('pdfProjectMessage',`
${e(err.message)}
`); } } async function renderPdfPage(){ if(!$('pdfCanvas') || !pdfStudio.pdfDocProxy) return; $('pdfViewerEmpty').style.display = 'none'; const page = await pdfStudio.pdfDocProxy.getPage(pdfStudio.page); const viewport = page.getViewport({scale:1.45}); const canvas = $('pdfCanvas'); const ctx = canvas.getContext('2d'); canvas.width = viewport.width; canvas.height = viewport.height; await page.render({canvasContext:ctx, viewport}).promise; $('pdfPagePill').textContent = `Page ${pdfStudio.page} / ${pdfStudio.pageCount}`; } function renderPdfReplacements(){ const body = $('pdfReplacementRows'); if(!body) return; if(!pdfStudio.replacements.length){ body.innerHTML = 'No replacements yet.'; return; } body.innerHTML = pdfStudio.replacements.map((r,i)=>``).join(''); body.querySelectorAll('input').forEach(inp => inp.oninput = () => { const i = Number(inp.dataset.i); const k = inp.dataset.k; pdfStudio.replacements[i][k] = k === 'page' ? Number(inp.value || 1) : inp.value; }); body.querySelectorAll('[data-del]').forEach(btn => btn.onclick = () => { pdfStudio.replacements.splice(Number(btn.dataset.del),1); renderPdfReplacements(); }); } async function aiMapPdfChanges(){ if(!pdfStudio.selectedTemplate){ pdfMsg('pdfProjectMessage','
Select a PDF template first.
'); return; } const prompt = $('pdfChangePrompt').value.trim(); if(!prompt){ pdfMsg('pdfProjectMessage','
Enter a prompt telling the OS what to change.
'); return; } try{ pdfMsg('pdfProjectMessage','
AI is mapping your instruction to PDF text replacements…
'); const result = await post('/api/brochure/pdf-templates/ai-map-changes', {template_id:pdfStudio.selectedTemplate.id, prompt_text:prompt, programme_name:$('pdfProgrammeName').value||'', extracted_text:pdfStudio.extractedText}); if(result.replacements && result.replacements.length){ pdfStudio.replacements = [...pdfStudio.replacements, ...result.replacements]; renderPdfReplacements(); pdfMsg('pdfProjectMessage',`
AI mapped ${result.replacements.length} replacement(s). Review before export.
`); }else{ pdfMsg('pdfProjectMessage','
No exact replacements found. Add changes manually or make the prompt more specific.
'); } }catch(err){ pdfMsg('pdfProjectMessage',`
${e(err.message)}
`); } } function addManualPdfReplacement(){ pdfStudio.replacements.push({page:pdfStudio.page||1, old_text:'', new_text:'', confidence:1, reason:'Manual'}); renderPdfReplacements(); } function findPdfTextMatch(rep){ const old = String(rep.old_text||'').toLowerCase().trim(); if(!old) return null; const page = Number(rep.page || 1); let exact = pdfStudio.extractedText.find(t => Number(t.page||1) === page && String(t.str||'').toLowerCase().trim() === old); if(exact) return exact; return pdfStudio.extractedText.find(t => Number(t.page||1) === page && String(t.str||'').toLowerCase().includes(old)); } function wrapPdfWords(text, maxChars){ const words = String(text||'').split(/\s+/).filter(Boolean); const lines=[]; let line=''; for(const w of words){ const cand = line ? line + ' ' + w : w; if(cand.length <= maxChars) line = cand; else { if(line) lines.push(line); line = w; } } if(line) lines.push(line); return lines.slice(0,5); } async function exportEditedPdf(){ if(!pdfStudio.pdfBytes || !pdfStudio.selectedTemplate){ pdfMsg('pdfExportMessage','
Select a PDF template first.
'); return; } if(!pdfStudio.replacements.length){ pdfMsg('pdfExportMessage','
Add at least one replacement first.
'); return; } try{ if(typeof PDFLib === 'undefined') throw new Error('PDF-Lib did not load. Check your internet connection or CDN access.'); pdfMsg('pdfExportMessage','
Generating edited PDF…
'); const pdfDoc = await PDFLib.PDFDocument.load(pdfStudio.pdfBytes); const font = await pdfDoc.embedFont(PDFLib.StandardFonts.Helvetica); const bold = await pdfDoc.embedFont(PDFLib.StandardFonts.HelveticaBold); const pages = pdfDoc.getPages(); let applied = 0; for(const rep of pdfStudio.replacements){ const match = findPdfTextMatch(rep); if(!match) continue; const page = pages[(Number(match.page)||1)-1]; if(!page) continue; const size = page.getSize(); const x = Math.max(0, Number(match.pdfX||0)-1); const y = Math.max(0, Number(match.pdfY||0)-2); const fs = Math.max(7, Math.min(18, Number(match.fontSize||10))); const oldWidth = Math.max(Number(match.width||0), font.widthOfTextAtSize(rep.old_text||'', fs)); const lines = wrapPdfWords(rep.new_text||'', Math.max(12, Math.floor((oldWidth+80)/(fs*0.48)))); const lineHeight = fs * 1.18; page.drawRectangle({x, y:y-2, width:Math.min(size.width-x-8, Math.max(oldWidth+8, 120)), height:Math.max(lineHeight*lines.length+6, fs+8), color:PDFLib.rgb(1,1,1), opacity:0.96}); lines.forEach((line,idx)=>page.drawText(line,{x:x+2, y:y+2+(lines.length-1-idx)*lineHeight, size:fs, font:idx===0?bold:font, color:PDFLib.rgb(0.02,0.16,0.13)})); applied++; } const bytes = await pdfDoc.save(); const blob = new Blob([bytes], {type:'application/pdf'}); const safe = ($('pdfProjectName').value || pdfStudio.selectedTemplate.template_name || 'edited-brochure').replace(/[^a-z0-9]+/gi,'-').replace(/^-|-$/g,'').toLowerCase(); saveBlob(blob, safe + '-edited.pdf'); pdfMsg('pdfExportMessage',`
Edited PDF generated and downloaded. Applied ${applied} replacement(s).
`); }catch(err){ pdfMsg('pdfExportMessage',`
${e(err.message)}
`); } } async function savePdfProject(){ if(!pdfStudio.selectedTemplate){ pdfMsg('pdfProjectMessage','
Select a PDF template first.
'); return; } try{ await post('/api/brochure/pdf-projects/save', {template_id:pdfStudio.selectedTemplate.id, project_name:$('pdfProjectName').value||'PDF brochure edit', programme_name:$('pdfProgrammeName').value||'', prompt_text:$('pdfChangePrompt').value||'', replacements:pdfStudio.replacements}); pdfMsg('pdfProjectMessage','
PDF project saved.
'); }catch(err){ pdfMsg('pdfProjectMessage',`
${e(err.message)}
`); } } function downloadOriginalPdfTemplate(){ if(!pdfStudio.selectedTemplate) return; window.open(api('/api/brochure/pdf-templates/file?id=' + encodeURIComponent(pdfStudio.selectedTemplate.id)), '_blank'); } function initPdfBrochureStudio(){ if(!$('pdfTemplateList')) return; if(typeof pdfjsLib !== 'undefined' && pdfjsLib.GlobalWorkerOptions){ pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; } ensureCoreReferenceData(); setSelectOptions('pdfTemplateSchool', optionList(state.schools, 'id', s => s.official_name || s.short_name || s.id, '', currentValue('pdfTemplateSchool'))); $('pdfUploadTemplateBtn').onclick = uploadPdfTemplate; $('pdfReloadTemplatesBtn').onclick = loadPdfTemplates; $('pdfAiMapBtn').onclick = aiMapPdfChanges; $('pdfAddManualBtn').onclick = addManualPdfReplacement; $('pdfSaveProjectBtn').onclick = savePdfProject; $('pdfExportBtn').onclick = exportEditedPdf; $('pdfExportBtnBottom').onclick = exportEditedPdf; $('pdfDownloadOriginalBtn').onclick = downloadOriginalPdfTemplate; $('pdfPrevPageBtn').onclick = async () => { if(pdfStudio.pdfDocProxy && pdfStudio.page > 1){ pdfStudio.page--; await renderPdfPage(); } }; $('pdfNextPageBtn').onclick = async () => { if(pdfStudio.pdfDocProxy && pdfStudio.page < pdfStudio.pageCount){ pdfStudio.page++; await renderPdfPage(); } }; loadPdfTemplates().catch(()=>{}); } document.addEventListener('DOMContentLoaded', async () => { ensureCoreReferenceData(); restoreFormState({}, true); $('apiBase').value = state.apiBase; $('adminName').value = state.adminName; renderEmailDropdowns(); renderIntakeSelectors(); renderFormatSelects(); renderFormats(); setAutoSync(state.autoSync); moduleButtons().forEach(link => link.addEventListener('click', event => { event.preventDefault(); showModule(link.dataset.module); })); $('saveApi').onclick = async () => { state.apiBase = $('apiBase').value.trim(); state.adminName = $('adminName').value.trim(); localStorage.setItem('admin_workspace_api_base', state.apiBase); localStorage.setItem('admin_workspace_name', state.adminName); await loadAll(); startAutoSync(); }; $('reloadData').onclick = async () => { state.apiBase = $('apiBase').value.trim(); localStorage.setItem('admin_workspace_api_base', state.apiBase); await loadAll(); startAutoSync(); }; $('toggleAutoSync').onclick = () => setAutoSync(!state.autoSync); document.addEventListener('visibilitychange', () => { if(!document.hidden && state.apiBase && state.autoSync && !(typeof isFormInteractionActive === 'function' && isFormInteractionActive())){ loadBaseData().catch(() => {}); } }); $('requestSearch').oninput = renderRequests; if($('formatSearch')) $('formatSearch').oninput = renderFormats; $('requestStatusFilter').onchange = renderRequests; $('requestPriorityFilter').onchange = renderRequests; if($('manualRequestToggleBtn')) $('manualRequestToggleBtn').onclick = () => toggleManualRequestPanel(); if($('manualRequestCancelBtn')) $('manualRequestCancelBtn').onclick = resetManualRequestForm; if($('manualRequestForm')) $('manualRequestForm').addEventListener('submit', handleManualRequestCreate); $('reviewRequestId').onchange = () => { state.selectedRequestId = $('reviewRequestId').value; localStorage.setItem('admin_workspace_selected_request', state.selectedRequestId); renderReview(); if($('editorRequestId')) $('editorRequestId').value = state.selectedRequestId; }; $('editorRequestId').onchange = () => { state.selectedRequestId = $('editorRequestId').value; localStorage.setItem('admin_workspace_selected_request', state.selectedRequestId); populateEditor(); if($('reviewRequestId')) $('reviewRequestId').value = state.selectedRequestId; }; $('showFilesBtn').onclick = () => { state.libraryMode = 'files'; renderLibrary(); }; if($('showPastAssetsBtn')) $('showPastAssetsBtn').onclick = () => { state.libraryMode = 'past'; renderLibrary(); }; $('showConceptsBtn').onclick = () => { state.libraryMode = 'concepts'; renderLibrary(); }; $('librarySearch').oninput = renderLibrary; $('emailForm').addEventListener('submit', handleEmailToRequest); if($('entityForm')) $('entityForm').addEventListener('submit', saveEntityMemory); if($('entityNewBtn')) $('entityNewBtn').onclick = newEntityMemory; if($('entityCancelEditBtn')) $('entityCancelEditBtn').onclick = newEntityMemory; if($('entityEditBtn')) $('entityEditBtn').onclick = editEntityMemory; if($('entityArchiveBtn')) $('entityArchiveBtn').onclick = archiveEntityMemory; if($('entitySeedBtn')) $('entitySeedBtn').onclick = seedDefaultEntities; $('brochureProjectId').onchange = () => openBrochureProject($('brochureProjectId').value); $('brochureNewBtn').onclick = clearBrochureForm; $('brochureSaveBtn').onclick = saveBrochureProject; $('brochureRegenerateBtn').onclick = regenerateBrochureProjectCopy; $('brochurePdfBtn').onclick = openBrochurePrintView; $('brochureOpenPrintBtn').onclick = openBrochurePrintView; const hash = (location.hash || '#home').replace('#',''); showModule(hash); if(state.apiBase){ try { await loadAll(); renderFormatSelects(); renderFormats(); } catch(err){ setConnection(false); connectionMessage(err.message, 'err'); } } initPdfBrochureStudio(); });