RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/AGENTS.md/REVREBEL/email-editor

AGENTS.md

AGENTS.md/AGENTS.md
AGENTS.md

Quality

49/100

Scores the file, not the repository.

Length

3,796 words

97 headings · 20 code blocks

Repository

0

— · pushed 0 days ago

Last changed

3 days ago

First indexed 3 days ago.
REVREBEL/email-editor/AGENTS.md/AGENTS.mdRawGitHub
1# Agent Brief — Vue Email Editor Integration (Unlayer)
2 
3## Project Goal
4 
5Integrate 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:
6 
7- Template Picker
8- File Manager & Custom Media Library
9- User Saved Blocks
10- Style Guide (design tokens / brand guardrails)
11- Merge Tags & Design Tags
12- Versioning & Autosave
13- Publishing workflow (draft → publish → usage)
14 
15This 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.
16 
17---
18 
19## High-Level Architecture
20 
21### Frontend (Vue 3 + Vite)
22- `vue-email-editor` component wrapper
23- State store (Pinia) for user/session, current template, save status
24- UI surfaces: Template Picker modal, File Manager modal, Saved Blocks, Style Guide panel, Merge/Design tag menus
25 
26### Backend (Node/Express or Nest)
27- REST/JSON endpoints for templates, designs, user blocks, media, tags
28- Auth middleware (JWT or session cookie) + RBAC for media/templates
29 
30### Database (PostgreSQL + Prisma)
31- Tables: `users`, `templates`, `versions`, `user_blocks`, `media_assets`, `merge_tags`, `design_tags`
32- Soft-deletes + versioning (immutable `versions` rows)
33 
34### Object Storage
35- S3-compatible (AWS S3, Cloudflare R2, GCS) for media assets
36- Signed upload URLs, MIME checks, image processing pipeline (optional)
37 
38### Queues (optional)
39- For heavy exports (HTML inlining, image optimization)
40 
41---
42 
43 
44# Agent Secret Access Documentation
45 
46To operate correctly, the agent requires access to sensitive credentials.
47These credentials are provided securely at runtime using the 1Password CLI tool.
48 
49**The agent should never contain hardcoded secrets.**
50 
51### Accessing Secrets
52 
53The secrets are exposed to the agent as standard environment variables within its
54runtime environment. The agent code must read these variables during initialization.
55 
56CLOUDFLARE_KEY The API Key for Cloudflare Storage op://AI/Cloudflare Storage API Key/credential
57POSTGRES_CONN_STR The full PostgreSQL connection string op://AI/PostgresSQL/connection string
58 
59Code Implementation (Example: Node.js)
60The agent should use its language's standard method for reading environment variables.
61 
62javascript
63// Example in Node.js/JavaScript
64const cloudflareKey = process.env.CLOUDFLARE_KEY;
65const postgresConnString = process.env.POSTGRES_CONN_STR;
66 
67if (!cloudflareKey || !postgresConnString) {
68 console.error("ERROR: Required secrets were not loaded into the environment.");
69 process.exit(1);
70}
71 
72// Proceed with agent logic...
73// useApiKey(cloudflareKey);
74// connectToDatabase(postgresConnString);
75 
76 
77## POSTGRES CONNECTION CREDENTIALS
78 
79** 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 same
82endpoint for the connection string to the network server at 192.168.8.105:5432
83including the db user and password.
84 
85 
86## Environment Variables (example)
87 
88```
89# Frontend (Vite)
90VITE_API_BASE=https://api.example.com
91VITE_UNLAYER_PROJECT_ID=xxxxxxxx
92 
93# Backend
94DATABASE_URL=postgresql://rebelbot:pass@192.168.8.105:5432/email_db
95JWT_SECRET=supersecret
96S3_ENDPOINT=https://s3.example.com
97S3_BUCKET=emails-media
98S3_ACCESS_KEY=...
99S3_SECRET_KEY=...
100CORS_ORIGIN=https://app.example.com
101```
102 
103---
104 
105## Core End-to-End Flows
106 
107### 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).
113 
114### 2. Versioning
115- 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.
118 
119### 3. Merge Tags
120- 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.
123 
124### 4. Media Assets
125- Upload to storage; store `storage_key` and `checksum`.
126- Signed URLs generated on demand (`public_url` optional).
127- Deduplicate on `(org_id, checksum)`.
128 
129### 5. Render & Preview
130- Compile `design_json` → HTML; substitute merge tags; inline CSS.
131- Generate **test sends** (rate-limited).
132- Capture renderer metadata for reproducibility.
133 
134### 6. Usage in Sending
135- 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.
138 
139### 7. Access Control & Audit
140- RBAC per org (Author / Publisher / Admin).
141- Audit logs: template changes, version publishes, asset uploads.
142 
143### 8. Webhooks & Events
144- `template.published`, `template.version.created`, `asset.created`, `send.previewed`
145 
146---
147 
148## Frontend Integration — Key Tasks
149 
150### 1. Start from `dev-example.vue`
151- Initialize `vue-email-editor`
152- Load merge tags, initial design
153- Implement `saveDesign`, `exportHtml`, `loadDesign` methods
154 
155### 2. Editor Event Plumbing
156- 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).
159 
160### 3. Editor Options
161- Template Picker
162- File Manager (custom picker + signed uploads)
163- Saved Blocks
164- Style Guide enforcement
165- Merge Tag registration
166- Design Tags form
167 
168### 4. Autosave
169- 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**
172 
173### 5. Export Pipeline
174- `exportHtml` → POST `/api/versions/:versionId/render`
175- Cache multiple export variants
176- Inline CSS, absolutize URLs, sanitize & minify output
177- Store compatibility results (e.g., linter results, deliverability checks)
178 
179### 6. Version Browser
180- Side panel list with author, timestamp
181- “Open as draft” and “Restore” actions
182 
183### 7. Publish Flow
184- Run linter → show grouped violations → block or warn based on severity
185 
186### 8. Merge-Tag Picker
187- Searchable; insert at cursor; preview with defaults
188 
189### 9. File Manager
190- Single picker UX across image/file tools
191- Thumbnails, folder support, drag-drop upload
192- AV scan (async) on upload
193- Responsive sizes and quotas with retention policies
194 
195---
196 
197## Guardrails & Invariants
198 
199- 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`.
205 
206### Style-Guide Guardrails
207- 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.
212 
213#### Example Style-Guide Tokens
214```json
215{
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": 400
243 },
244 "layout": {
245 "maxWidth": 640
246 },
247 "padding": {
248 "btn": {
249 "top": 20,
250 "right": 24,
251 "bottom": 20,
252 "left": 24
253 }
254 },
255 "radius": {
256 "btn": 3
257 },
258 "spacing": {
259 "btn": 8,
260 "contentGutter": 24,
261 "sectionGap": 32
262 }
263}
264```
265 
266---
267 
268## Database Schema (Finalized)
269 
270```sql
271-- templates
272id (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_at
282 
283-- versions
284id (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)
297 
298-- media_assets
299id (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_at
310unique (org_id, checksum)
311 
312-- merge_tags
313id (uuid pk)
314org_id (uuid fk -> orgs)
315key (citext)
316label (text)
317default_value (text)
318system (boolean default false)
319created_at, updated_at
320unique (org_id, key)
321```
322 
323### Schema Extensions & Advanced Tables
324 
325- `organizations`, `org_members`, `template_collaborators` for multi-tenancy & permissions
326- `exports` table for multiple cached variants
327- `jobs` table for AV scans, thumbnails, heavy exports
328- `audit_logs` table for traceability
329 
330---
331 
332## Backend API (Contract)
333 
334### Templates & Versions
335- `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`
346 
347### Media
348- `GET /api/media`
349- `POST /api/media/sign`
350- `GET /api/media/:id/url`
351- `DELETE /api/media/:id`
352 
353### API Additions
354- `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`
360 
361---
362 
363### Templates & Versions
364- `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`
375 
376---
377 
378## Testing Plan
379 
380### Media
381- `GET /api/media`
382- `POST /api/media/sign`
383- `GET /api/media/:id/url`
384- `DELETE /api/media/:id`
385 
386### API Additions
387- `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`
393 
394### Tags Additions
395**Tags**
396 
397- [ ] Multi-tenant model & collaborator permissions
398- [ ] Editor event hooks wired (dirty, autosave, export)
399- [ ] Style-guide tokens + linter + publish gate
400- [ ] Exports, jobs, audit_logs, template_collaborators tables
401- [ ] Draft vs published semantics clarified and implemented
402- [ ] File Manager override + AV scan + thumbnails + quotas
403- [ ] CSP/CORS, pooling, backups, metrics
404- [ ] Tight indexes & scoped uniqueness
405- [ ] Secrets only in `.env.example`
406 
407---
408 
409## DevOps / Platform Considerations
410 
411- **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.
418 
419---
420 
421## Testing Plan
422 
423- **Contract tests**: editor bridges (load/save/export, media select)
424- **Snapshot tests**: exported HTML (goldens)
425- **Security tests**: object-level auth across orgs
426- **E2E tests**: full flow — create → edit → autosave → publish → export
427 
428---
429 
430## Definition of Done (Checklist)
431 
432- [ ] Multi-tenant model & collaborator permissions
433- [ ] Editor event hooks wired (dirty, autosave, export)
434- [ ] Style-guide tokens + linter + publish gate
435- [ ] Exports, jobs, audit_logs, template_collaborators tables
436- [ ] Draft vs published semantics clarified and implemented
437- [ ] File Manager override + AV scan + thumbnails + quotas
438- [ ] CSP/CORS, pooling, backups, metrics
439- [ ] Tight indexes & scoped uniqueness
440- [ ] Secrets only in `.env.example`
441 
442---
443 
444## Spec Addendum (Summary)
445 
446- 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.
453 
454## ⚙️ Local Development Notes
455 
456* **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.
457 
458* **Port Consistency:** Keep the local dev server port fixed in `vite.config.ts` at:
459 
460```ts
461 server: {
462 port: 9022
463 }
464```
465 
466* **Network Flow / Reverse Proxy Setup:**
467 External requests from outside IPs follow this path:
468 
469```
470 SSL :443 (External Request)
471 ↓
472 Reverse Proxy Server
473 ↓
474 Local Dev Server (192.168.8.137:9022)
475```
476 
477This ensures stable connections during testing and remote access, while avoiding conflicts with the agent runtime.
478 
479 
480## Issues
481- 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.
483 
484 
485## Resolved
486- 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.
489 
490---
491 
492## 🧰 Issue Template
493 
494### Issue [#] | [MM-DD-YYYY]
495 
496**Title:** [Short, descriptive title of the issue]
497 
498**Description:**
499[Detailed description of the issue, how it was discovered, and any reproduction steps if relevant.]
500 
501**Impact:**
502[What part of the system is affected and how it impacts users or workflows.]
503 
504**Status:** Open
505**Priority:** [Low | Medium | High | Critical]
506**Owner:** [Team or individual responsible]
507**Reference:** [Optional: internal tracking ID, issue number, or ticket link]
508 
509---
510 
511### RESOLVED | [MM-DD-YYYY]
512 
513**Resolution Summary:**
514[Brief explanation of the fix or solution implemented.]
515 
516**Commit:** [Commit hash or link]
517**Linked PR:** [PR number or link]
518**Verified By:** [QA name or date]
519 
520---
521 
522## ✅ Examples — Real Issue
523 
524### Issue 1 | 10-19-2025
525 
526**Title:** Autosave fails silently when the editor tab loses focus.
527 
528**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.
530 
531**Impact:**
532 
533* Draft data can be lost unexpectedly.
534* Increases user frustration and reduces trust in autosave reliability.
535 
536**Status:** Open
537**Priority:** High
538**Owner:** Frontend Integration Team
539**Reference:** `editor_autosave_event_bug`
540 
541---
542 
543### RESOLVED | 10-25-2025
544 
545**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.
549 
550**Commit:** [`abc1234`](https://github.com/REVREBEL/email-editor/commit/abc1234)
551**Linked PR:** #42
552**Verified By:** QA on staging (10-24-2025)
553 
554 
555---
556 
557# Unlayer Features & Docs Map
558 
559When 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.
560 
561## App Pages to Add (Builder Modes)
562 
563> Each page demonstrates a different `displayMode` with a minimal `unlayer.init(...)` example.
564 
565### 1) Page Builder (Web)
566**Docs:** `./AGENTS.md/unlayer-builder/page-builder.md`
567 
568```js
569unlayer.init({
570 id: 'editor-container',
571 displayMode: 'web',
572 projectId: 1234 // REPLACE
573});
574```
575 
576### 2) Document Builder
577**Docs:** `./AGENTS.md/unlayer-builder/document-builder.md`
578 
579```js
580unlayer.init({
581 id: 'editor-container',
582 displayMode: 'document',
583 projectId: 1234 // REPLACE
584});
585```
586 
587### 3) Popup Builder
588**Docs:** `./AGENTS.md/builder/popup-builder.md`
589 
590```js
591unlayer.init({
592 id: 'editor-container',
593 displayMode: 'popup',
594 projectId: 1234 // REPLACE
595});
596```
597 
598### Export Example (all modes)
599```js
600unlayer.exportHtml(console.log, { title: 'Exported HTML Title' });
601```
602 
603---
604 
605## Feature Flags & Native SDK (Allowed)
606 
607> The following should use **Unlayer native functions** (not custom components), per our implementation policy.
608 
609### Headers & Footers
610Enable via feature flag:
611 
612```js
613unlayer.init({
614 features: {
615 headersAndFooters: true
616 }
617});
618```
619 
620### Page Anchors
621**Docs:** (See “Page Anchors” notes in builder docs) — lets users link buttons/links to sections of the page.
622 
623```js
624unlayer.init({
625 features: {
626 pageAnchors: true
627 }
628});
629```
630 
631### Connect Your CDN (Optional)
632Use native Unlayer integration so assets leverage CloudFront) for faster loads.
633**Docs:** `./AGENTS.md/builder/file-storage/custom.md`
634 
635Use Tool 1Password: Get from 1Password.
636 
637Cloudflare API Key
638"op run://AI/Cloudflare Storage API Key/credential"
639"op run:op://AI/PostgresSQL/connection string"
640Connection URL
641"op run://AI/Cloudflare Storage API Key/hostname"
642 
643 
644---
645 
646## Custom File Storage (Native Callbacks)
647 
648**Docs:** `./AGENTS.md/builder/file-storage/custom.md`
649 
650Register Unlayer’s native `image` callback to control uploads:
651 
652```js
653unlayer.registerCallback('image', function (file, done) {
654 // Handle file upload here (POST to your storage/signing endpoint)
655 // Example: immediately show some progress
656 done({ progress: 10 });
657});
658```
659 
660**Update progress bar during upload:**
661```js
662unlayer.registerCallback('image', function (file, done) {
663 // ... upload chunk ...
664 done({ progress: 10 });
665 // ... upload chunk ...
666 done({ progress: 50 });
667});
668```
669 
670**Finish upload with final URL:**
671```js
672unlayer.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```
677 
678---
679 
680## Templates (On Your Own Servers)
681**Docs:** `./AGENTS.md/builder/templates/management.md`
682 
683Load a template JSON directly:
684 
685```js
686const template = { /* Unlayer design JSON */ };
687unlayer.loadDesign(template);
688```
689 
690---
691 
692## Custom Tools & Blocks (Native)
693 
694> Prefer Unlayer’s native extension points for tools/blocks; only build a heavy custom component if the SDK cannot cover the use case.
695 
696- **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`
701 
702---
703 
704## Text Management
705 
706- **Tables (Enable):** `./AGENTS.md/builder/text-management/tables`
707- **Spell Checker (Enable):** `./AGENTS.md/builder/text-management/spell-checker.md`
708```js
709 unlayer.init({
710 features: {
711 textEditor: {
712 spellChecker: true
713 }
714 }
715 });
716```
717- **Inline Font Controls (Enable):** `./AGENTS.md/builder/text-management/inline-font-controls.md`
718```js
719 unlayer.init({
720 features: {
721 textEditor: {
722 inlineFontControls: true
723 }
724 }
725 });
726```
727 
728---
729 
730## Device Support
731 
732**Docs:** `./AGENTS.md/builder/device-management.md`
733 
734```js
735unlayer.init({
736 devices: ['desktop', 'mobile']
737});
738```
739 
740---
741 
742### Implementation Notes
743 
744- **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.
748 
749 
750### Template Picker
751 
752* 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).
754 
755### File Manager & Custom Media Library
756 
757* 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.
760 
761### User Saved Blocks
762 
763* 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.
765 
766### Style Guide
767 
768* 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`.
771 
772### Merge Tags
773 
774* 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.
776 
777### Design Tags
778 
779* Free-form key/value for analytics & downstream automation (e.g., `campaign_id`, `segment`).
780 
781### User Template Updates
782 
783* Autosave drafts; manual version bump on Save.
784* Show status (Draft/Published) and save indicator (saving / saved).
785 
786---
787 
788 
789## Security & Compliance
790 
791* 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.
797 
798---
799 
800## Testing Strategy
801 
802* 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.
805 
806---
807 
808## Deliverables
809 
810* 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.
816 
817---
818 
819## Resources Needed
820 
821* 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.
827 
828---
829 
830 
831## Frontend Integration — Key Tasks
832 
8331. **Start from `dev-example.vue`**
834 
835 * 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.
838 
839- 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.
846 
847## ⚙️ Local Development Notes
848 
849* **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.
850 
851* **Port Consistency:** Keep the local dev server port fixed in `vite.config.ts` at:
852 
853```ts
854 server: {
855 port: 9022
856 }
857```
858 
859* **Network Flow / Reverse Proxy Setup:**
860 External requests from outside IPs follow this path:
861 
862```
863 SSL :443 (External Request)
864 ↓
865 Reverse Proxy Server
866 ↓
867 Local Dev Server (192.168.8.137:9022)
868```
869 
870This ensures stable connections during testing and remote access, while avoiding conflicts with the agent runtime.
871 
872 
873## Issues
874- 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.
876 
877 
878## Resolved
879- 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.
882 
883---
884 
885## 🧰 Issue Template
886 
887### Issue [#] | [MM-DD-YYYY]
888 
889**Title:** [Short, descriptive title of the issue]
890 
891**Description:**
892[Detailed description of the issue, how it was discovered, and any reproduction steps if relevant.]
893 
894**Impact:**
895[What part of the system is affected and how it impacts users or workflows.]
896 
897**Status:** Open
898**Priority:** [Low | Medium | High | Critical]
899**Owner:** [Team or individual responsible]
900**Reference:** [Optional: internal tracking ID, issue number, or ticket link]
901 
902---
903 
904### RESOLVED | [MM-DD-YYYY]
905 
906**Resolution Summary:**
907[Brief explanation of the fix or solution implemented.]
908 
909**Commit:** [Commit hash or link]
910**Linked PR:** [PR number or link]
911**Verified By:** [QA name or date]
912 
913---
914 
915## ✅ Examples — Real Issue
916 
917### Issue 1 | 10-19-2025
918 
919**Title:** Autosave fails silently when the editor tab loses focus.
920 
921**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.
923 
924**Impact:**
925 
926* Draft data can be lost unexpectedly.
927* Increases user frustration and reduces trust in autosave reliability.
928 
929**Status:** Open
930**Priority:** High
931**Owner:** Frontend Integration Team
932**Reference:** `editor_autosave_event_bug`
933 
934---
935 
936 
937## Definition of Done
938 
939* 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.
942 
943---
944 

Sections

  • Agent Brief — Vue Email Editor Integration (Unlayer)
  • Project Goal
  • High-Level Architecture
  • Frontend (Vue 3 + Vite)
  • Backend (Node/Express or Nest)
  • Database (PostgreSQL + Prisma)
  • Object Storage
  • Queues (optional)
  • Agent Secret Access Documentation
  • Accessing Secrets
  • POSTGRES CONNECTION CREDENTIALS
  • Environment Variables (example)
  • Frontend (Vite)
  • Backend
  • Core End-to-End Flows
  • 1. Template Lifecycle (Draft → Publish → Use)
  • 2. Versioning
  • 3. Merge Tags
  • 4. Media Assets
  • 5. Render & Preview
  • 6. Usage in Sending
  • 7. Access Control & Audit
  • 8. Webhooks & Events
  • Frontend Integration — Key Tasks
  • 1. Start from `dev-example.vue`
  • 2. Editor Event Plumbing
  • 3. Editor Options
  • 4. Autosave
  • 5. Export Pipeline
  • 6. Version Browser
  • 7. Publish Flow
  • 8. Merge-Tag Picker
  • 9. File Manager
  • Guardrails & Invariants
  • Style-Guide Guardrails
  • Database Schema (Finalized)
  • Schema Extensions & Advanced Tables
  • Backend API (Contract)
  • Templates & Versions
  • Media
  • API Additions
  • Templates & Versions
  • Testing Plan
  • Media
  • API Additions
  • Tags Additions
  • DevOps / Platform Considerations
  • Testing Plan
  • Definition of Done (Checklist)
  • Spec Addendum (Summary)
  • ⚙️ Local Development Notes
  • Issues
  • Resolved
  • 🧰 Issue Template
  • Issue [#] | [MM-DD-YYYY]
  • RESOLVED | [MM-DD-YYYY]
  • ✅ Examples — Real Issue
  • Issue 1 | 10-19-2025
  • RESOLVED | 10-25-2025
  • Unlayer Features & Docs Map

What it covers

setuptestcode-styletypesgit-prsecuritydatabaseapideploymentdo-notagent-behaviourdocs

Stack — with the evidence

typescript

(1.00)

javascript

(1.00)

prisma

(1.00)

vite

(1.00)

eslint

(1.00)

node

(0.75)

vue

(0.70)

express

(0.70)

aws

(0.70)

monorepo

(0.60)

pnpm

(0.60)

docker

(0.60)

github-actions

(0.60)

Format

AGENTS.md

A plain-markdown README for coding agents, deliberately unopinionated: no frontmatter, no globs, no vendor keys. That minimalism is why it became the one file a dozen different agents will read, and why it carries the least per-file targeting power of any format here.

What the corpus says about it

Repository

Owner
REVREBEL
Language
—
License
—
Archived
no

All configs in this repo

Also in REVREBEL/email-editor

Diff this repo’s formats

One 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?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
REVREBEL/email-editorAGENTS.md/GEMINI.md · 0GEMINI.mdtypescriptjavascript+11setupteststyletypes+849/1003 days ago
Diff against AGENTS.md/GEMINI.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199kAGENTS.mdtypescriptlangchain+16buildteststylearch+3100/1003 days ago
aaif-goose/gooseAGENTS.md · 52kAGENTS.mdrusttypescript+2setupbuildtestlint-format+6100/1003 days ago
wpscanteam/wpscanAGENTS.md · 9.7kAGENTS.mdrubyvue+3setupbuildteststyle+6100/1002 days ago
mui/material-uiAGENTS.md · 99kAGENTS.mdtypescriptjavascript+13setupbuildtestlint-format+9100/1003 days ago
SkeneTechnologies/skene-cookbookAGENTS.md · 51AGENTS.mdpythoneslint+4setupbuildtestlint-format+7100/1002 days ago
duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70AGENTS.mdtypescriptjavascript+5buildteststylearch+3100/1003 days ago
trick77/agents-md-syncAGENTS.md · 2AGENTS.mdtypescriptnode+4setupbuildteststyle+5100/1003 days ago
TryGhost/Ghoste2e/AGENTS.md · 55kAGENTS.mdtypescriptjavascript+12setupteststylearch+2100/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack