AGENTS.md
AGENTS.md/AGENTS.mdAGENTS.md
Quality
49/100
Scores the file, not the repository.Length
3,796 words
97 headings · 20 code blocksRepository
0
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.1# Agent Brief — Vue Email Editor Integration (Unlayer)23## Project Goal45Integrate the **Unlayer Vue Email Editor** (`vue-email-editor`) into a Vue app, modernize the configuration, and add a persistence & media layer so users can **create, edit, version, and publish email designs** to **PostgreSQL**, with support for:67- Template Picker8- File Manager & Custom Media Library9- User Saved Blocks10- Style Guide (design tokens / brand guardrails)11- Merge Tags & Design Tags12- Versioning & Autosave13- Publishing workflow (draft → publish → usage)1415This brief serves as the single source of truth for both **product and engineering** — describing the high-level vision, architecture, backend contracts, data model, DevOps considerations, and operational guardrails.1617---1819## High-Level Architecture2021### Frontend (Vue 3 + Vite)22- `vue-email-editor` component wrapper23- State store (Pinia) for user/session, current template, save status24- UI surfaces: Template Picker modal, File Manager modal, Saved Blocks, Style Guide panel, Merge/Design tag menus2526### Backend (Node/Express or Nest)27- REST/JSON endpoints for templates, designs, user blocks, media, tags28- Auth middleware (JWT or session cookie) + RBAC for media/templates2930### Database (PostgreSQL + Prisma)31- Tables: `users`, `templates`, `versions`, `user_blocks`, `media_assets`, `merge_tags`, `design_tags`32- Soft-deletes + versioning (immutable `versions` rows)3334### Object Storage35- S3-compatible (AWS S3, Cloudflare R2, GCS) for media assets36- Signed upload URLs, MIME checks, image processing pipeline (optional)3738### Queues (optional)39- For heavy exports (HTML inlining, image optimization)4041---424344# Agent Secret Access Documentation4546To operate correctly, the agent requires access to sensitive credentials.47These credentials are provided securely at runtime using the 1Password CLI tool.4849**The agent should never contain hardcoded secrets.**5051### Accessing Secrets5253The secrets are exposed to the agent as standard environment variables within its54runtime environment. The agent code must read these variables during initialization.5556CLOUDFLARE_KEY The API Key for Cloudflare Storage op://AI/Cloudflare Storage API Key/credential57POSTGRES_CONN_STR The full PostgreSQL connection string op://AI/PostgresSQL/connection string5859Code Implementation (Example: Node.js)60The agent should use its language's standard method for reading environment variables.6162javascript63// Example in Node.js/JavaScript64const cloudflareKey = process.env.CLOUDFLARE_KEY;65const postgresConnString = process.env.POSTGRES_CONN_STR;6667if (!cloudflareKey || !postgresConnString) {68 console.error("ERROR: Required secrets were not loaded into the environment.");69 process.exit(1);70}7172// Proceed with agent logic...73// useApiKey(cloudflareKey);74// connectToDatabase(postgresConnString);757677## POSTGRES CONNECTION CREDENTIALS7879** The Postgres Database is hosted on a local nework server.80It's NOT running on docker on this machine.81Connect using either of the option below, both contain the same82endpoint for the connection string to the network server at 192.168.8.105:543283including the db user and password.848586## Environment Variables (example)8788```89# Frontend (Vite)90VITE_API_BASE=https://api.example.com91VITE_UNLAYER_PROJECT_ID=xxxxxxxx9293# Backend94DATABASE_URL=postgresql://rebelbot:pass@192.168.8.105:5432/email_db95JWT_SECRET=supersecret96S3_ENDPOINT=https://s3.example.com97S3_BUCKET=emails-media98S3_ACCESS_KEY=...99S3_SECRET_KEY=...100CORS_ORIGIN=https://app.example.com101```102103---104105## Core End-to-End Flows106107### 1. Template Lifecycle (Draft → Publish → Use)108- **Create Template**: Name + org → auto-create initial **Draft v1**.109- **Edit Draft**: Update content (`design_json`), preview HTML, autosave.110- **Publish**: Locks draft and sets `currentPublishedVersionId`. Draft remains editable or is cleared.111- **Fork New Draft**: Create a new draft from the published version.112- **Archive**: Soft-delete templates (never delete versions).113114### 2. Versioning115- Templates have at most **one current draft** and **one current published version**.116- Publishing locks a version (`locked=true`, `status=PUBLISHED`).117- Version numbers increment sequentially per template.118119### 3. Merge Tags120- Defined **per org** with unique `(org_id, key)`.121- System tags (e.g., `{{ unsubscribe_url }}`) are reserved.122- Unknown tags → validation error with list of unknown keys.123124### 4. Media Assets125- Upload to storage; store `storage_key` and `checksum`.126- Signed URLs generated on demand (`public_url` optional).127- Deduplicate on `(org_id, checksum)`.128129### 5. Render & Preview130- Compile `design_json` → HTML; substitute merge tags; inline CSS.131- Generate **test sends** (rate-limited).132- Capture renderer metadata for reproducibility.133134### 6. Usage in Sending135- External systems reference `template_id` + optional `version_id`.136- If `version_id` is omitted → latest `currentPublishedVersionId` is used.137- Audit logs record which version was rendered.138139### 7. Access Control & Audit140- RBAC per org (Author / Publisher / Admin).141- Audit logs: template changes, version publishes, asset uploads.142143### 8. Webhooks & Events144- `template.published`, `template.version.created`, `asset.created`, `send.previewed`145146---147148## Frontend Integration — Key Tasks149150### 1. Start from `dev-example.vue`151- Initialize `vue-email-editor`152- Load merge tags, initial design153- Implement `saveDesign`, `exportHtml`, `loadDesign` methods154155### 2. Editor Event Plumbing156- Listen for `design:updated` (dirty state) → throttled autosave (5–10s).157- Register merge tags on load and persist last-used set per org/user.158- Override media selection to route through your File Manager (custom picker → returns URL to Unlayer).159160### 3. Editor Options161- Template Picker162- File Manager (custom picker + signed uploads)163- Saved Blocks164- Style Guide enforcement165- Merge Tag registration166- Design Tags form167168### 4. Autosave169- Throttled autosave → `POST /api/templates/:id/autosave`170- Cancel on route leave; show states: *Saving… / Saved / Failed*171- On revisit, if autosave is newer than draft, prompt to **Restore**172173### 5. Export Pipeline174- `exportHtml` → POST `/api/versions/:versionId/render`175- Cache multiple export variants176- Inline CSS, absolutize URLs, sanitize & minify output177- Store compatibility results (e.g., linter results, deliverability checks)178179### 6. Version Browser180- Side panel list with author, timestamp181- “Open as draft” and “Restore” actions182183### 7. Publish Flow184- Run linter → show grouped violations → block or warn based on severity185186### 8. Merge-Tag Picker187- Searchable; insert at cursor; preview with defaults188189### 9. File Manager190- Single picker UX across image/file tools191- Thumbnails, folder support, drag-drop upload192- AV scan (async) on upload193- Responsive sizes and quotas with retention policies194195---196197## Guardrails & Invariants198199- Published versions are immutable (`locked=true`).200- Drafts are the only mutable state.201- Merge tags unique per org (case-insensitive).202- Media URLs are derived from `storage_key`; ephemeral signed URLs should never be persisted.203- Assets cannot be deleted if referenced by any version.204- Publish without a draft → `409 Conflict`.205206### Style-Guide Guardrails207- Central JSON of brand tokens (colors, fonts, radii, spacing).208- Pre-publish/export **linter**:209 - Reject/warn on non-approved fonts/colors/line-heights.210 - Enforce alt text and basic contrast checks.211- Optionally lock disallowed tools/colors in Unlayer options.212213#### Example Style-Guide Tokens214```json215{216 "colors": {217 "background": {218 "dark": "#B2D3DE",219 "light": "#FAFAFA"220 },221 "brandPrimary": "#163666",222 "brandSecondary": "#B2D3DE",223 "button": {224 "dark": "#163666",225 "light": "#B2D3DE"226 },227 "danger": "#F37D59",228 "error": "#E05047",229 "info": "#B2D3DE",230 "textDark": "#0B1320",231 "textLight": "#334155",232 "warning": "#FACA78"233 },234 "fontFamily": {235 "btn": "'Khand', 'Oswald', 'Impact', sans-serif",236 "header": "'Khand', 'Oswald', 'Impact', sans-serif",237 "primary": "'General Sans', 'Public Sans', 'Inter', 'Andale Mono', Tahoma, sans-serif"238 },239 "fontWeight": {240 "btn": 700,241 "header": 700,242 "primary": 400243 },244 "layout": {245 "maxWidth": 640246 },247 "padding": {248 "btn": {249 "top": 20,250 "right": 24,251 "bottom": 20,252 "left": 24253 }254 },255 "radius": {256 "btn": 3257 },258 "spacing": {259 "btn": 8,260 "contentGutter": 24,261 "sectionGap": 32262 }263}264```265266---267268## Database Schema (Finalized)269270```sql271-- templates272id (uuid pk)273org_id (uuid fk -> orgs)274name (text)275slug (text unique)276status (text check in ['draft','published','archived'])277current_draft_version_id (uuid fk -> versions null)278current_published_version_id (uuid fk -> versions null)279style_guide_id (uuid null)280deleted_at (timestamp null)281created_at, updated_at282283-- versions284id (uuid pk)285template_id (uuid fk -> templates)286number (int)287status (text check in ['DRAFT','PUBLISHED'])288design_json (jsonb)289html_compiled (text)290renderer_name (text)291renderer_ver (text)292inliner_ver (text)293created_by (uuid fk -> users)294created_at (timestamp)295published_at (timestamp)296locked (boolean default false)297298-- media_assets299id (uuid pk)300org_id (uuid fk -> orgs)301filename (text)302content_type (text)303byte_size (int)304storage_key (text)305public_url (text null)306checksum (text)307meta (jsonb)308created_by (uuid fk -> users)309created_at, updated_at, deleted_at310unique (org_id, checksum)311312-- merge_tags313id (uuid pk)314org_id (uuid fk -> orgs)315key (citext)316label (text)317default_value (text)318system (boolean default false)319created_at, updated_at320unique (org_id, key)321```322323### Schema Extensions & Advanced Tables324325- `organizations`, `org_members`, `template_collaborators` for multi-tenancy & permissions326- `exports` table for multiple cached variants327- `jobs` table for AV scans, thumbnails, heavy exports328- `audit_logs` table for traceability329330---331332## Backend API (Contract)333334### Templates & Versions335- `POST /api/templates`336- `GET /api/templates`337- `GET /api/templates/:id`338- `PATCH /api/templates/:id`339- `POST /api/templates/:id/versions`340- `GET /api/templates/:id/versions`341- `GET /api/versions/:versionId`342- `POST /api/versions/:versionId`343- `POST /api/versions/:versionId/publish`344- `POST /api/versions/:versionId/render`345- `POST /api/versions/:versionId/test-send`346347### Media348- `GET /api/media`349- `POST /api/media/sign`350- `GET /api/media/:id/url`351- `DELETE /api/media/:id`352353### API Additions354- `POST /api/templates/:id/duplicate`355- `GET /api/templates/:id/exports`356- `GET /api/templates/:id/exports/:exportId`357- `POST /api/media/scan/:id`358- `GET /api/style-guide`359- `POST /api/webhooks`, `GET /api/webhooks/events`360361---362363### Templates & Versions364- `POST /api/templates`365- `GET /api/templates`366- `GET /api/templates/:id`367- `PATCH /api/templates/:id`368- `POST /api/templates/:id/versions`369- `GET /api/templates/:id/versions`370- `GET /api/versions/:versionId`371- `POST /api/versions/:versionId`372- `POST /api/versions/:versionId/publish`373- `POST /api/versions/:versionId/render`374- `POST /api/versions/:versionId/test-send`375376---377378## Testing Plan379380### Media381- `GET /api/media`382- `POST /api/media/sign`383- `GET /api/media/:id/url`384- `DELETE /api/media/:id`385386### API Additions387- `POST /api/templates/:id/duplicate`388- `GET /api/templates/:id/exports`389- `GET /api/templates/:id/exports/:exportId`390- `POST /api/media/scan/:id`391- `GET /api/style-guide`392- `POST /api/webhooks`, `GET /api/webhooks/events`393394### Tags Additions395**Tags**396397- [ ] Multi-tenant model & collaborator permissions398- [ ] Editor event hooks wired (dirty, autosave, export)399- [ ] Style-guide tokens + linter + publish gate400- [ ] Exports, jobs, audit_logs, template_collaborators tables401- [ ] Draft vs published semantics clarified and implemented402- [ ] File Manager override + AV scan + thumbnails + quotas403- [ ] CSP/CORS, pooling, backups, metrics404- [ ] Tight indexes & scoped uniqueness405- [ ] Secrets only in `.env.example`406407---408409## DevOps / Platform Considerations410411- **CORS/CSP**: Allow Unlayer iframe domain; set `img-src`/`media-src` to CDN + `data:`.412- **DB Pooling**: Use pgbouncer or node-pg pool.413- **Migrations/Seeds**: Seed org, users, template, tags, media.414- **Observability**: Include `request_id`, `user_id`, `org_id` in logs.415- **Metrics**: saves/sec, exports latency, AV scan times.416- **Backups**: Daily PG snapshots; media lifecycle rules (IA/Glacier).417- **Secrets**: Only `.env.example`; never commit real credentials.418419---420421## Testing Plan422423- **Contract tests**: editor bridges (load/save/export, media select)424- **Snapshot tests**: exported HTML (goldens)425- **Security tests**: object-level auth across orgs426- **E2E tests**: full flow — create → edit → autosave → publish → export427428---429430## Definition of Done (Checklist)431432- [ ] Multi-tenant model & collaborator permissions433- [ ] Editor event hooks wired (dirty, autosave, export)434- [ ] Style-guide tokens + linter + publish gate435- [ ] Exports, jobs, audit_logs, template_collaborators tables436- [ ] Draft vs published semantics clarified and implemented437- [ ] File Manager override + AV scan + thumbnails + quotas438- [ ] CSP/CORS, pooling, backups, metrics439- [ ] Tight indexes & scoped uniqueness440- [ ] Secrets only in `.env.example`441442---443444## Spec Addendum (Summary)445446- One draft and one published version per template.447- Published versions are immutable.448- Merge tags scoped per org.449- Signed URLs are ephemeral and derived at read-time.450- Compiled HTML cached for current published version.451- Signed URL TTL default: 15 minutes.452- Metrics: render latency, publish latency, error rates.453454## ⚙️ Local Development Notes455456* **Server Control:** When working on local development, please let me handle starting and stopping the dev server — manual restarts during active work can cause the agent to freeze or lose state.457458* **Port Consistency:** Keep the local dev server port fixed in `vite.config.ts` at:459460```ts461 server: {462 port: 9022463 }464```465466* **Network Flow / Reverse Proxy Setup:**467 External requests from outside IPs follow this path:468469```470 SSL :443 (External Request)471 ↓472 Reverse Proxy Server473 ↓474 Local Dev Server (192.168.8.137:9022)475```476477This ensures stable connections during testing and remote access, while avoiding conflicts with the agent runtime.478479480## Issues481- Review the AGENT_issues.md file for a list of current open issues.482- Use this file as the source of truth for tracking bugs, feature gaps, tech debt, and pending decisions.483484485## Resolved486- When an issue listed in AGENT_issues.md is confirmed fixed or completed, move that exact line into AGENT_resolved.md.487- Immediately below the original line, add the tag RESOLVED followed by the data and include a brief summary of the high-level steps taken to resolve it.488- This ensures historical traceability and keeps the issues list clean while preserving context for future reference.489490---491492## 🧰 Issue Template493494### Issue [#] | [MM-DD-YYYY]495496**Title:** [Short, descriptive title of the issue]497498**Description:**499[Detailed description of the issue, how it was discovered, and any reproduction steps if relevant.]500501**Impact:**502[What part of the system is affected and how it impacts users or workflows.]503504**Status:** Open505**Priority:** [Low | Medium | High | Critical]506**Owner:** [Team or individual responsible]507**Reference:** [Optional: internal tracking ID, issue number, or ticket link]508509---510511### RESOLVED | [MM-DD-YYYY]512513**Resolution Summary:**514[Brief explanation of the fix or solution implemented.]515516**Commit:** [Commit hash or link]517**Linked PR:** [PR number or link]518**Verified By:** [QA name or date]519520---521522## ✅ Examples — Real Issue523524### Issue 1 | 10-19-2025525526**Title:** Autosave fails silently when the editor tab loses focus.527528**Description:**529Users reported that when the browser tab is backgrounded during editing, the `design:updated` event is not always triggered. As a result, autosave does not fire, leading to potential data loss if the tab is closed or refreshed before a manual save.530531**Impact:**532533* Draft data can be lost unexpectedly.534* Increases user frustration and reduces trust in autosave reliability.535536**Status:** Open537**Priority:** High538**Owner:** Frontend Integration Team539**Reference:** `editor_autosave_event_bug`540541---542543### RESOLVED | 10-25-2025544545**Resolution Summary:**546✅ Added a visibility change listener to trigger a final autosave before the tab loses focus.547✅ Implemented a fallback debounce timer to ensure autosave fires even if the event is skipped.548✅ Added logging and metrics to monitor autosave failures in production.549550**Commit:** [`abc1234`](https://github.com/REVREBEL/email-editor/commit/abc1234)551**Linked PR:** #42552**Verified By:** QA on staging (10-24-2025)553554555---556557# Unlayer Features & Docs Map558559When implementing functionality, prefer **custom components** over broad Unlayer SDK expansion—**except** for the explicitly whitelisted “Use Unlayer Native Function: True” items below. The official Unlayer documentation has been added under `./AGENTS.md/*`. Use the relative links in this section to find the correct doc quickly.560561## App Pages to Add (Builder Modes)562563> Each page demonstrates a different `displayMode` with a minimal `unlayer.init(...)` example.564565### 1) Page Builder (Web)566**Docs:** `./AGENTS.md/unlayer-builder/page-builder.md`567568```js569unlayer.init({570 id: 'editor-container',571 displayMode: 'web',572 projectId: 1234 // REPLACE573});574```575576### 2) Document Builder577**Docs:** `./AGENTS.md/unlayer-builder/document-builder.md`578579```js580unlayer.init({581 id: 'editor-container',582 displayMode: 'document',583 projectId: 1234 // REPLACE584});585```586587### 3) Popup Builder588**Docs:** `./AGENTS.md/builder/popup-builder.md`589590```js591unlayer.init({592 id: 'editor-container',593 displayMode: 'popup',594 projectId: 1234 // REPLACE595});596```597598### Export Example (all modes)599```js600unlayer.exportHtml(console.log, { title: 'Exported HTML Title' });601```602603---604605## Feature Flags & Native SDK (Allowed)606607> The following should use **Unlayer native functions** (not custom components), per our implementation policy.608609### Headers & Footers610Enable via feature flag:611612```js613unlayer.init({614 features: {615 headersAndFooters: true616 }617});618```619620### Page Anchors621**Docs:** (See “Page Anchors” notes in builder docs) — lets users link buttons/links to sections of the page.622623```js624unlayer.init({625 features: {626 pageAnchors: true627 }628});629```630631### Connect Your CDN (Optional)632Use native Unlayer integration so assets leverage CloudFront) for faster loads.633**Docs:** `./AGENTS.md/builder/file-storage/custom.md`634635Use Tool 1Password: Get from 1Password.636637Cloudflare API Key638"op run://AI/Cloudflare Storage API Key/credential"639"op run:op://AI/PostgresSQL/connection string"640Connection URL641"op run://AI/Cloudflare Storage API Key/hostname"642643644---645646## Custom File Storage (Native Callbacks)647648**Docs:** `./AGENTS.md/builder/file-storage/custom.md`649650Register Unlayer’s native `image` callback to control uploads:651652```js653unlayer.registerCallback('image', function (file, done) {654 // Handle file upload here (POST to your storage/signing endpoint)655 // Example: immediately show some progress656 done({ progress: 10 });657});658```659660**Update progress bar during upload:**661```js662unlayer.registerCallback('image', function (file, done) {663 // ... upload chunk ...664 done({ progress: 10 });665 // ... upload chunk ...666 done({ progress: 50 });667});668```669670**Finish upload with final URL:**671```js672unlayer.registerCallback('image', function (file, done) {673 // After your upload finishes:674 done({ progress: 100, url: 'https://cdn.example.com/path/to/image.jpg' });675});676```677678---679680## Templates (On Your Own Servers)681**Docs:** `./AGENTS.md/builder/templates/management.md`682683Load a template JSON directly:684685```js686const template = { /* Unlayer design JSON */ };687unlayer.loadDesign(template);688```689690---691692## Custom Tools & Blocks (Native)693694> Prefer Unlayer’s native extension points for tools/blocks; only build a heavy custom component if the SDK cannot cover the use case.695696- **Create Custom Tools (Docs):** `./AGENTS.md/builder/tools/custom/create.md`697- **Inject CSS/JS from Tools (Docs):** `./AGENTS.md/builder/tools/custom/css-javascript.md`698 > Each tool can insert CSS/JS into <head> if you prefer non-inline styles.699- **Custom Blocks (Docs):** `./AGENTS.md/builder/blocks/custom.md`700- **User Saved Blocks (Docs):** `./AGENTS.md/builder/blocks/user-saved.md`701702---703704## Text Management705706- **Tables (Enable):** `./AGENTS.md/builder/text-management/tables`707- **Spell Checker (Enable):** `./AGENTS.md/builder/text-management/spell-checker.md`708```js709 unlayer.init({710 features: {711 textEditor: {712 spellChecker: true713 }714 }715 });716```717- **Inline Font Controls (Enable):** `./AGENTS.md/builder/text-management/inline-font-controls.md`718```js719 unlayer.init({720 features: {721 textEditor: {722 inlineFontControls: true723 }724 }725 });726```727728---729730## Device Support731732**Docs:** `./AGENTS.md/builder/device-management.md`733734```js735unlayer.init({736 devices: ['desktop', 'mobile']737});738```739740---741742### Implementation Notes743744- **Policy:** Default to **custom components** for new functionality, **except** where this section explicitly says “Use Unlayer Native Function: True.”745- **Docs Source:** All linked docs are local to this repo under `./AGENTS.md/...` so they remain versioned with the project.746- **Project ID:** Replace `projectId` in examples with your Unlayer Project ID.747- **Export Pipeline:** Use native `exportHtml` and route the output through our **export fidelity pipeline** (inlining, absolutizing, sanitizing)—see “Export Pipeline” section earlier in this doc.748749750### Template Picker751752* Server: paginate templates by owner/status; include `current_version_id` & version meta.753* Client: searchable list, preview thumbnail (render HTML server-side once & screenshot optional).754755### File Manager & Custom Media Library756757* Use signed upload URLs to object storage; DB stores metadata + URL.758* Image validation (mime, dims), size limits, per-user folders.759* Selection returns absolute URL that the editor can embed.760761### User Saved Blocks762763* Store each block as JSON fragment compatible with Unlayer’s block structure.764* Offer categories and preview thumbnails; insert by calling the editor’s add/merge API.765766### Style Guide767768* Centralize tokens (fonts, colors, spacings) in one config file.769* Lock or hide non-approved tools/colors via editor options when possible.770* Pre-export linter to detect rogue colors or non-approved fonts in `design_json`.771772### Merge Tags773774* Provide a curated list with labels and defaults (e.g., `user.first_name`, `hotel.name`).775* Ensure the list syncs with your ESP/templating engine expectations.776777### Design Tags778779* Free-form key/value for analytics & downstream automation (e.g., `campaign_id`, `segment`).780781### User Template Updates782783* Autosave drafts; manual version bump on Save.784* Show status (Draft/Published) and save indicator (saving / saved).785786---787788789## Security & Compliance790791* AuthN: JWT cookies (httpOnly, secure) or session.792* AuthZ: Enforce ownership and roles on all endpoints.793* Input validation: Zod/Valibot for request bodies.794* Media: antivirus scan (ClamAV) if required; signed URLs with short TTL.795* Audit trail for create/update/delete.796* Rate limiting + CORS allow-list.797798---799800## Testing Strategy801802* Unit: API handlers (templates, versions, media) with in-memory PG or test DB.803* Integration: Save → Load → Export using a headless browser against the editor.804* E2E: Cypress flows covering Template Picker, Media upload, Saved Blocks, Merge Tags insertion, Export.805806---807808## Deliverables809810* Vue app with `vue-email-editor` integrated and all feature UIs.811* Node/Express backend + Prisma schema & migrations.812* Postgres SQL dump (baseline).813* API docs (OpenAPI/Swagger) covering endpoints above.814* Admin-only seed script with demo templates, merge tags, and media samples.815* README with setup, env, and run instructions.816817---818819## Resources Needed820821* Access to the `vue-email-editor` repo & `dev-example.vue`.822* Unlayer account / Project ID (if required by advanced features).823* Postgres instance & credentials.824* S3-compatible storage (bucket, keys).825* Domain for API (for CORS) and OAuth provider if SSO desired.826* Brand tokens: fonts, colors, spacing, logo assets.827828---829830831## Frontend Integration — Key Tasks8328331. **Start from `dev-example.vue`**834835 * Ensure ref access to editor (`<EmailEditor ref="editorRef" :options="editorOptions" @load="onLoad" />`).836 * Implement `onLoad` to set config, load initial design if `template.current_version` exists.837 * Expose `saveDesign`, `exportHtml`, `loadDesign` via methods bound to UI buttons.838839- One draft and one published version per template.840- Published versions are immutable.841- Merge tags scoped per org.842- Signed URLs are ephemeral and derived at read-time.843- Compiled HTML cached for current published version.844- Signed URL TTL default: 15 minutes.845- Metrics: render latency, publish latency, error rates.846847## ⚙️ Local Development Notes848849* **Server Control:** When working on local development, please let me handle starting and stopping the dev server — manual restarts during active work can cause the agent to freeze or lose state.850851* **Port Consistency:** Keep the local dev server port fixed in `vite.config.ts` at:852853```ts854 server: {855 port: 9022856 }857```858859* **Network Flow / Reverse Proxy Setup:**860 External requests from outside IPs follow this path:861862```863 SSL :443 (External Request)864 ↓865 Reverse Proxy Server866 ↓867 Local Dev Server (192.168.8.137:9022)868```869870This ensures stable connections during testing and remote access, while avoiding conflicts with the agent runtime.871872873## Issues874- Review the AGENT_issues.md file for a list of current open issues.875- Use this file as the source of truth for tracking bugs, feature gaps, tech debt, and pending decisions.876877878## Resolved879- When an issue listed in AGENT_issues.md is confirmed fixed or completed, move that exact line into AGENT_resolved.md.880- Immediately below the original line, add the tag RESOLVED followed by the data and include a brief summary of the high-level steps taken to resolve it.881- This ensures historical traceability and keeps the issues list clean while preserving context for future reference.882883---884885## 🧰 Issue Template886887### Issue [#] | [MM-DD-YYYY]888889**Title:** [Short, descriptive title of the issue]890891**Description:**892[Detailed description of the issue, how it was discovered, and any reproduction steps if relevant.]893894**Impact:**895[What part of the system is affected and how it impacts users or workflows.]896897**Status:** Open898**Priority:** [Low | Medium | High | Critical]899**Owner:** [Team or individual responsible]900**Reference:** [Optional: internal tracking ID, issue number, or ticket link]901902---903904### RESOLVED | [MM-DD-YYYY]905906**Resolution Summary:**907[Brief explanation of the fix or solution implemented.]908909**Commit:** [Commit hash or link]910**Linked PR:** [PR number or link]911**Verified By:** [QA name or date]912913---914915## ✅ Examples — Real Issue916917### Issue 1 | 10-19-2025918919**Title:** Autosave fails silently when the editor tab loses focus.920921**Description:**922Users reported that when the browser tab is backgrounded during editing, the `design:updated` event is not always triggered. As a result, autosave does not fire, leading to potential data loss if the tab is closed or refreshed before a manual save.923924**Impact:**925926* Draft data can be lost unexpectedly.927* Increases user frustration and reduces trust in autosave reliability.928929**Status:** Open930**Priority:** High931**Owner:** Frontend Integration Team932**Reference:** `editor_autosave_event_bug`933934---935936937## Definition of Done938939* Users can: pick a template, edit, insert media via custom file manager, use saved blocks, apply style guide, insert merge/design tags, autosave, version, and export HTML.940* All data persisted in Postgres; media stored and retrievable.941* Tests green; docs complete; lint/format pass; CI pipeline in place.942943---944
Also in REVREBEL/email-editor
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| REVREBEL/email-editorAGENTS.md/GEMINI.md · 0 | GEMINI.md | setupteststyletypes+8 | 49/100 | 3 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199k | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| aaif-goose/gooseAGENTS.md · 52k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| wpscanteam/wpscanAGENTS.md · 9.7k | AGENTS.md | setupbuildteststyle+6 | 100/100 | 2 days ago | |
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 3 days ago | |
| SkeneTechnologies/skene-cookbookAGENTS.md · 51 | AGENTS.md | setupbuildtestlint-format+7 | 100/100 | 2 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| trick77/agents-md-syncAGENTS.md · 2 | AGENTS.md | setupbuildteststyle+5 | 100/100 | 3 days ago | |
| TryGhost/Ghoste2e/AGENTS.md · 55k | AGENTS.md | setupteststylearch+2 | 100/100 | 3 days ago |
