GEMINI.md
AGENTS.md/GEMINI.mdGEMINI.md
Quality
49/100
Scores the file, not the repository.Length
3,818 words
98 headings · 20 code blocksRepository
0
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.1# Gemini Agent Brief — Vue Email Editor Integration (Unlayer)2# Agent Brief — Vue Email Editor Integration (Unlayer)34** history can be found in the chat folder for reference **56## Project Goal78Integrate 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:910- Template Picker11- File Manager & Custom Media Library12- User Saved Blocks13- Style Guide (design tokens / brand guardrails)14- Merge Tags & Design Tags15- Versioning & Autosave16- Publishing workflow (draft → publish → usage)1718This 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.1920---2122## High-Level Architecture2324### Frontend (Vue 3 + Vite)25- `vue-email-editor` component wrapper26- State store (Pinia) for user/session, current template, save status27- UI surfaces: Template Picker modal, File Manager modal, Saved Blocks, Style Guide panel, Merge/Design tag menus2829### Backend (Node/Express or Nest)30- REST/JSON endpoints for templates, designs, user blocks, media, tags31- Auth middleware (JWT or session cookie) + RBAC for media/templates3233### Database (PostgreSQL + Prisma)34- Tables: `users`, `templates`, `versions`, `user_blocks`, `media_assets`, `merge_tags`, `design_tags`35- Soft-deletes + versioning (immutable `versions` rows)3637### Object Storage38- S3-compatible (AWS S3, Cloudflare R2, GCS) for media assets39- Signed upload URLs, MIME checks, image processing pipeline (optional)4041### Queues (optional)42- For heavy exports (HTML inlining, image optimization)4344---454647# Agent Secret Access Documentation4849To operate correctly, the agent requires access to sensitive credentials.50These credentials are provided securely at runtime using the 1Password CLI tool.5152**The agent should never contain hardcoded secrets.**5354### Accessing Secrets5556The secrets are exposed to the agent as standard environment variables within its57runtime environment. The agent code must read these variables during initialization.5859CLOUDFLARE_KEY The API Key for Cloudflare Storage op://AI/Cloudflare Storage API Key/credential60POSTGRES_CONN_STR The full PostgreSQL connection string op://AI/PostgresSQL/connection string6162Code Implementation (Example: Node.js)63The agent should use its language's standard method for reading environment variables.6465javascript66// Example in Node.js/JavaScript67const cloudflareKey = process.env.CLOUDFLARE_KEY;68const postgresConnString = process.env.POSTGRES_CONN_STR;6970if (!cloudflareKey || !postgresConnString) {71 console.error("ERROR: Required secrets were not loaded into the environment.");72 process.exit(1);73}7475// Proceed with agent logic...76// useApiKey(cloudflareKey);77// connectToDatabase(postgresConnString);787980## POSTGRES CONNECTION CREDENTIALS8182** The Postgres Database is hosted on a local network server.83It's NOT running on docker on this machine.84Connect using either of the options below, both contain the same85endpoint for the connection string to the network server at 192.168.8.105:543286including the db user and password.878889## Environment Variables (example)9091```92# Frontend (Vite)93VITE_API_BASE=https://api.example.com94VITE_UNLAYER_PROJECT_ID=xxxxxxxx9596# Backend97DATABASE_URL=postgresql://rebelbot:pass@192.168.8.105:5432/email_db98JWT_SECRET=supersecret99S3_ENDPOINT=https://s3.example.com100S3_BUCKET=emails-media101S3_ACCESS_KEY=...102S3_SECRET_KEY=...103CORS_ORIGIN=https://app.example.com104```105106---107108## Core End-to-End Flows109110### 1. Template Lifecycle (Draft → Publish → Use)111- **Create Template**: Name + org → auto-create initial **Draft v1**.112- **Edit Draft**: Update content (`design_json`), preview HTML, autosave.113- **Publish**: Locks draft and sets `currentPublishedVersionId`. Draft remains editable or is cleared.114- **Fork New Draft**: Create a new draft from the published version.115- **Archive**: Soft-delete templates (never delete versions).116117### 2. Versioning118- Templates have at most **one current draft** and **one current published version**.119- Publishing locks a version (`locked=true`, `status=PUBLISHED`).120- Version numbers increment sequentially per template.121122### 3. Merge Tags123- Defined **per org** with unique `(org_id, key)`.124- System tags (e.g., `{{ unsubscribe_url }}`) are reserved.125- Unknown tags → validation error with list of unknown keys.126127### 4. Media Assets128- Upload to storage; store `storage_key` and `checksum`.129- Signed URLs generated on demand (`public_url` optional).130- Deduplicate on `(org_id, checksum)`.131132### 5. Render & Preview133- Compile `design_json` → HTML; substitute merge tags; inline CSS.134- Generate **test sends** (rate-limited).135- Capture renderer metadata for reproducibility.136137### 6. Usage in Sending138- External systems reference `template_id` + optional `version_id`.139- If `version_id` is omitted → latest `currentPublishedVersionId` is used.140- Audit logs record which version was rendered.141142### 7. Access Control & Audit143- RBAC per org (Author / Publisher / Admin).144- Audit logs: template changes, version publishes, asset uploads.145146### 8. Webhooks & Events147- `template.published`, `template.version.created`, `asset.created`, `send.previewed`148149---150151## Frontend Integration — Key Tasks152153### 1. Start from `dev-example.vue`154- Initialize `vue-email-editor`155- Load merge tags, initial design156- Implement `saveDesign`, `exportHtml`, `loadDesign` methods157158### 2. Editor Event Plumbing159- Listen for `design:updated` (dirty state) → throttled autosave (5–10s).160- Register merge tags on load and persist last-used set per org/user.161- Override media selection to route through your File Manager (custom picker → returns URL to Unlayer).162163### 3. Editor Options164- Template Picker165- File Manager (custom picker + signed uploads)166- Saved Blocks167- Style Guide enforcement168- Merge Tag registration169- Design Tags form170171### 4. Autosave172- Throttled autosave → `POST /api/templates/:id/autosave`173- Cancel on route leave; show states: *Saving… / Saved / Failed*174- On revisit, if autosave is newer than draft, prompt to **Restore**175176### 5. Export Pipeline177- `exportHtml` → POST `/api/versions/:versionId/render`178- Cache multiple export variants179- Inline CSS, absolutize URLs, sanitize & minify output180- Store compatibility results (e.g., linter results, deliverability checks)181182### 6. Version Browser183- Side panel list with author, timestamp184- “Open as draft” and “Restore” actions185186### 7. Publish Flow187- Run linter → show grouped violations → block or warn based on severity188189### 8. Merge-Tag Picker190- Searchable; insert at cursor; preview with defaults191192### 9. File Manager193- Single picker UX across image/file tools194- Thumbnails, folder support, drag-drop upload195- AV scan (async) on upload196- Responsive sizes and quotas with retention policies197198---199200## Guardrails & Invariants201202- Published versions are immutable (`locked=true`).203- Drafts are the only mutable state.204- Merge tags unique per org (case-insensitive).205- Media URLs are derived from `storage_key`; ephemeral signed URLs should never be persisted.206- Assets cannot be deleted if referenced by any version.207- Publish without a draft → `409 Conflict`.208209### Style-Guide Guardrails210- Central JSON of brand tokens (colors, fonts, radii, spacing).211- Pre-publish/export **linter**:212 - Reject/warn on non-approved fonts/colors/line-heights.213 - Enforce alt text and basic contrast checks.214- Optionally lock disallowed tools/colors in Unlayer options.215216#### Example Style-Guide Tokens217```json218{219 "colors": {220 "background": {221 "dark": "#B2D3DE",222 "light": "#FAFAFA"223 },224 "brandPrimary": "#163666",225 "brandSecondary": "#B2D3DE",226 "button": {227 "dark": "#163666",228 "light": "#B2D3DE"229 },230 "danger": "#F37D59",231 "error": "#E05047",232 "info": "#B2D3DE",233 "textDark": "#0B1320",234 "textLight": "#334155",235 "warning": "#FACA78"236 },237 "fontFamily": {238 "btn": "'Khand', 'Oswald', 'Impact', sans-serif",239 "header": "'Khand', 'Oswald', 'Impact', sans-serif",240 "primary": "'General Sans', 'Public Sans', 'Inter', 'Andale Mono', Tahoma, sans-serif"241 },242 "fontWeight": {243 "btn": 700,244 "header": 700,245 "primary": 400246 },247 "layout": {248 "maxWidth": 640249 },250 "padding": {251 "btn": {252 "top": 20,253 "right": 24,254 "bottom": 20,255 "left": 24256 }257 },258 "radius": {259 "btn": 3260 },261 "spacing": {262 "btn": 8,263 "contentGutter": 24,264 "sectionGap": 32265 }266}267```268269---270271## Database Schema (Finalized)272273```sql274-- templates275id (uuid pk)276org_id (uuid fk -> orgs)277name (text)278slug (text unique)279status (text check in ['draft','published','archived'])280current_draft_version_id (uuid fk -> versions null)281current_published_version_id (uuid fk -> versions null)282style_guide_id (uuid null)283deleted_at (timestamp null)284created_at, updated_at285286-- versions287id (uuid pk)288template_id (uuid fk -> templates)289number (int)290status (text check in ['DRAFT','PUBLISHED'])291design_json (jsonb)292html_compiled (text)293renderer_name (text)294renderer_ver (text)295inliner_ver (text)296created_by (uuid fk -> users)297created_at (timestamp)298published_at (timestamp)299locked (boolean default false)300301-- media_assets302id (uuid pk)303org_id (uuid fk -> orgs)304filename (text)305content_type (text)306byte_size (int)307storage_key (text)308public_url (text null)309checksum (text)310meta (jsonb)311created_by (uuid fk -> users)312created_at, updated_at, deleted_at313unique (org_id, checksum)314315-- merge_tags316id (uuid pk)317org_id (uuid fk -> orgs)318key (citext)319label (text)320default_value (text)321system (boolean default false)322created_at, updated_at323unique (org_id, key)324```325326### Schema Extensions & Advanced Tables327328- `organizations`, `org_members`, `template_collaborators` for multi-tenancy & permissions329- `exports` table for multiple cached variants330- `jobs` table for AV scans, thumbnails, heavy exports331- `audit_logs` table for traceability332333---334335## Backend API (Contract)336337### Templates & Versions338- `POST /api/templates`339- `GET /api/templates`340- `GET /api/templates/:id`341- `PATCH /api/templates/:id`342- `POST /api/templates/:id/versions`343- `GET /api/templates/:id/versions`344- `GET /api/versions/:versionId`345- `POST /api/versions/:versionId`346- `POST /api/versions/:versionId/publish`347- `POST /api/versions/:versionId/render`348- `POST /api/versions/:versionId/test-send`349350### Media351- `GET /api/media`352- `POST /api/media/sign`353- `GET /api/media/:id/url`354- `DELETE /api/media/:id`355356### API Additions357- `POST /api/templates/:id/duplicate`358- `GET /api/templates/:id/exports`359- `GET /api/templates/:id/exports/:exportId`360- `POST /api/media/scan/:id`361- `GET /api/style-guide`362- `POST /api/webhooks`, `GET /api/webhooks/events`363364---365366### Templates & Versions367- `POST /api/templates`368- `GET /api/templates`369- `GET /api/templates/:id`370- `PATCH /api/templates/:id`371- `POST /api/templates/:id/versions`372- `GET /api/templates/:id/versions`373- `GET /api/versions/:versionId`374- `POST /api/versions/:versionId`375- `POST /api/versions/:versionId/publish`376- `POST /api/versions/:versionId/render`377- `POST /api/versions/:versionId/test-send`378379---380381## Testing Plan382383### Media384- `GET /api/media`385- `POST /api/media/sign`386- `GET /api/media/:id/url`387- `DELETE /api/media/:id`388389### API Additions390- `POST /api/templates/:id/duplicate`391- `GET /api/templates/:id/exports`392- `GET /api/templates/:id/exports/:exportId`393- `POST /api/media/scan/:id`394- `GET /api/style-guide`395- `POST /api/webhooks`, `GET /api/webhooks/events`396397### Tags Additions398**Tags**399400- [ ] Multi-tenant model & collaborator permissions401- [ ] Editor event hooks wired (dirty, autosave, export)402- [ ] Style-guide tokens + linter + publish gate403- [ ] Exports, jobs, audit_logs, template_collaborators tables404- [ ] Draft vs published semantics clarified and implemented405- [ ] File Manager override + AV scan + thumbnails + quotas406- [ ] CSP/CORS, pooling, backups, metrics407- [ ] Tight indexes & scoped uniqueness408- [ ] Secrets only in `.env.example`409410---411412## DevOps / Platform Considerations413414- **CORS/CSP**: Allow Unlayer iframe domain; set `img-src`/`media-src` to CDN + `data:`.415- **DB Pooling**: Use pgbouncer or node-pg pool.416- **Migrations/Seeds**: Seed org, users, template, tags, media.417- **Observability**: Include `request_id`, `user_id`, `org_id` in logs.418- **Metrics**: saves/sec, exports latency, AV scan times.419- **Backups**: Daily PG snapshots; media lifecycle rules (IA/Glacier).420- **Secrets**: Only `.env.example`; never commit real credentials.421422---423424## Testing Plan425426- **Contract tests**: editor bridges (load/save/export, media select)427- **Snapshot tests**: exported HTML (goldens)428- **Security tests**: object-level auth across orgs429- **E2E tests**: full flow — create → edit → autosave → publish → export430431---432433## Definition of Done (Checklist)434435- [ ] Multi-tenant model & collaborator permissions436- [ ] Editor event hooks wired (dirty, autosave, export)437- [ ] Style-guide tokens + linter + publish gate438- [ ] Exports, jobs, audit_logs, template_collaborators tables439- [ ] Draft vs published semantics clarified and implemented440- [ ] File Manager override + AV scan + thumbnails + quotas441- [ ] CSP/CORS, pooling, backups, metrics442- [ ] Tight indexes & scoped uniqueness443- [ ] Secrets only in `.env.example`444445---446447## Spec Addendum (Summary)448449- One draft and one published version per template.450- Published versions are immutable.451- Merge tags scoped per org.452- Signed URLs are ephemeral and derived at read-time.453- Compiled HTML cached for current published version.454- Signed URL TTL default: 15 minutes.455- Metrics: render latency, publish latency, error rates.456457## ⚙️ Local Development Notes458459* **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.460461* **Port Consistency:** Keep the local dev server port fixed in `vite.config.ts` at:462463```ts464 server: {465 port: 9022466 }467```468469* **Network Flow / Reverse Proxy Setup:**470 External requests from outside IPs follow this path:471472```473 SSL :443 (External Request)474 ↓475 Reverse Proxy Server476 ↓477 Local Dev Server (192.168.8.137:9022)478```479480This ensures stable connections during testing and remote access, while avoiding conflicts with the agent runtime.481482483## Issues484- Review the AGENT_issues.md file for a list of current open issues.485- Use this file as the source of truth for tracking bugs, feature gaps, tech debt, and pending decisions.486487488## Resolved489- When an issue listed in AGENT_issues.md is confirmed fixed or completed, move that exact line into AGENT_resolved.md.490- 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.491- This ensures historical traceability and keeps the issues list clean while preserving context for future reference.492493---494495## 🧰 Issue Template496497### Issue [#] | [MM-DD-YYYY]498499**Title:** [Short, descriptive title of the issue]500501**Description:**502[Detailed description of the issue, how it was discovered, and any reproduction steps if relevant.]503504**Impact:**505[What part of the system is affected and how it impacts users or workflows.]506507**Status:** Open508**Priority:** [Low | Medium | High | Critical]509**Owner:** [Team or individual responsible]510**Reference:** [Optional: internal tracking ID, issue number, or ticket link]511512---513514### RESOLVED | [MM-DD-YYYY]515516**Resolution Summary:**517[Brief explanation of the fix or solution implemented.]518519**Commit:** [Commit hash or link]520**Linked PR:** [PR number or link]521**Verified By:** [QA name or date]522523---524525## ✅ Examples — Real Issue526527### Issue 1 | 10-19-2025528529**Title:** Autosave fails silently when the editor tab loses focus.530531**Description:**532Users 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.533534**Impact:**535536* Draft data can be lost unexpectedly.537* Increases user frustration and reduces trust in autosave reliability.538539**Status:** Open540**Priority:** High541**Owner:** Frontend Integration Team542**Reference:** `editor_autosave_event_bug`543544---545546### RESOLVED | 10-25-2025547548**Resolution Summary:**549✅ Added a visibility change listener to trigger a final autosave before the tab loses focus.550✅ Implemented a fallback debounce timer to ensure autosave fires even if the event is skipped.551✅ Added logging and metrics to monitor autosave failures in production.552553**Commit:** [`abc1234`](https://github.com/REVREBEL/email-editor/commit/abc1234)554**Linked PR:** #42555**Verified By:** QA on staging (10-24-2025)556557558---559560# Unlayer Features & Docs Map561562When 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.563564## App Pages to Add (Builder Modes)565566> Each page demonstrates a different `displayMode` with a minimal `unlayer.init(...)` example.567568### 1) Page Builder (Web)569**Docs:** `./AGENTS.md/unlayer-builder/page-builder.md`570571```js572unlayer.init({573 id: 'editor-container',574 displayMode: 'web',575 projectId: 1234 // REPLACE576});577```578579### 2) Document Builder580**Docs:** `./AGENTS.md/unlayer-builder/document-builder.md`581582```js583unlayer.init({584 id: 'editor-container',585 displayMode: 'document',586 projectId: 1234 // REPLACE587});588```589590### 3) Popup Builder591**Docs:** `./AGENTS.md/builder/popup-builder.md`592593```js594unlayer.init({595 id: 'editor-container',596 displayMode: 'popup',597 projectId: 1234 // REPLACE598});599```600601### Export Example (all modes)602```js603unlayer.exportHtml(console.log, { title: 'Exported HTML Title' });604```605606---607608## Feature Flags & Native SDK (Allowed)609610> The following should use **Unlayer native functions** (not custom components), per our implementation policy.611612### Headers & Footers613Enable via feature flag:614615```js616unlayer.init({617 features: {618 headersAndFooters: true619 }620});621```622623### Page Anchors624**Docs:** (See “Page Anchors” notes in builder docs) — lets users link buttons/links to sections of the page.625626```js627unlayer.init({628 features: {629 pageAnchors: true630 }631});632```633634### Connect Your CDN (Optional)635Use native Unlayer integration so assets leverage CloudFront) for faster loads.636**Docs:** `./AGENTS.md/builder/file-storage/custom.md`637638Use Tool 1Password: Get from 1Password.639640Cloudflare API Key641"op run://AI/Cloudflare Storage API Key/credential"642"op run:op://AI/PostgresSQL/connection string"643Connection URL644"op run://AI/Cloudflare Storage API Key/hostname"645646647---648649## Custom File Storage (Native Callbacks)650651**Docs:** `./AGENTS.md/builder/file-storage/custom.md`652653Register Unlayer’s native `image` callback to control uploads:654655```js656unlayer.registerCallback('image', function (file, done) {657 // Handle file upload here (POST to your storage/signing endpoint)658 // Example: immediately show some progress659 done({ progress: 10 });660});661```662663**Update progress bar during upload:**664```js665unlayer.registerCallback('image', function (file, done) {666 // ... upload chunk ...667 done({ progress: 10 });668 // ... upload chunk ...669 done({ progress: 50 });670});671```672673**Finish upload with final URL:**674```js675unlayer.registerCallback('image', function (file, done) {676 // After your upload finishes:677 done({ progress: 100, url: 'https://cdn.example.com/path/to/image.jpg' });678});679```680681---682683## Templates (On Your Own Servers)684**Docs:** `./AGENTS.md/builder/templates/management.md`685686Load a template JSON directly:687688```js689const template = { /* Unlayer design JSON */ };690unlayer.loadDesign(template);691```692693---694695## Custom Tools & Blocks (Native)696697> Prefer Unlayer’s native extension points for tools/blocks; only build a heavy custom component if the SDK cannot cover the use case.698699- **Create Custom Tools (Docs):** `./AGENTS.md/builder/tools/custom/create.md`700- **Inject CSS/JS from Tools (Docs):** `./AGENTS.md/builder/tools/custom/css-javascript.md`701 > Each tool can insert CSS/JS into <head> if you prefer non-inline styles.702- **Custom Blocks (Docs):** `./AGENTS.md/builder/blocks/custom.md`703- **User Saved Blocks (Docs):** `./AGENTS.md/builder/blocks/user-saved.md`704705---706707## Text Management708709- **Tables (Enable):** `./AGENTS.md/builder/text-management/tables`710- **Spell Checker (Enable):** `./AGENTS.md/builder/text-management/spell-checker.md`711```js712 unlayer.init({713 features: {714 textEditor: {715 spellChecker: true716 }717 }718 });719```720- **Inline Font Controls (Enable):** `./AGENTS.md/builder/text-management/inline-font-controls.md`721```js722 unlayer.init({723 features: {724 textEditor: {725 inlineFontControls: true726 }727 }728 });729```730731---732733## Device Support734735**Docs:** `./AGENTS.md/builder/device-management.md`736737```js738unlayer.init({739 devices: ['desktop', 'mobile']740});741```742743---744745### Implementation Notes746747- **Policy:** Default to **custom components** for new functionality, **except** where this section explicitly says “Use Unlayer Native Function: True.”748- **Docs Source:** All linked docs are local to this repo under `./AGENTS.md/...` so they remain versioned with the project.749- **Project ID:** Replace `projectId` in examples with your Unlayer Project ID.750- **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.751752753### Template Picker754755* Server: paginate templates by owner/status; include `current_version_id` & version meta.756* Client: searchable list, preview thumbnail (render HTML server-side once & screenshot optional).757758### File Manager & Custom Media Library759760* Use signed upload URLs to object storage; DB stores metadata + URL.761* Image validation (mime, dims), size limits, per-user folders.762* Selection returns absolute URL that the editor can embed.763764### User Saved Blocks765766* Store each block as JSON fragment compatible with Unlayer’s block structure.767* Offer categories and preview thumbnails; insert by calling the editor’s add/merge API.768769### Style Guide770771* Centralize tokens (fonts, colors, spacings) in one config file.772* Lock or hide non-approved tools/colors via editor options when possible.773* Pre-export linter to detect rogue colors or non-approved fonts in `design_json`.774775### Merge Tags776777* Provide a curated list with labels and defaults (e.g., `user.first_name`, `hotel.name`).778* Ensure the list syncs with your ESP/templating engine expectations.779780### Design Tags781782* Free-form key/value for analytics & downstream automation (e.g., `campaign_id`, `segment`).783784### User Template Updates785786* Autosave drafts; manual version bump on Save.787* Show status (Draft/Published) and save indicator (saving / saved).788789---790791792## Security & Compliance793794* AuthN: JWT cookies (httpOnly, secure) or session.795* AuthZ: Enforce ownership and roles on all endpoints.796* Input validation: Zod/Valibot for request bodies.797* Media: antivirus scan (ClamAV) if required; signed URLs with short TTL.798* Audit trail for create/update/delete.799* Rate limiting + CORS allow-list.800801---802803## Testing Strategy804805* Unit: API handlers (templates, versions, media) with in-memory PG or test DB.806* Integration: Save → Load → Export using a headless browser against the editor.807* E2E: Cypress flows covering Template Picker, Media upload, Saved Blocks, Merge Tags insertion, Export.808809---810811## Deliverables812813* Vue app with `vue-email-editor` integrated and all feature UIs.814* Node/Express backend + Prisma schema & migrations.815* Postgres SQL dump (baseline).816* API docs (OpenAPI/Swagger) covering endpoints above.817* Admin-only seed script with demo templates, merge tags, and media samples.818* README with setup, env, and run instructions.819820---821822## Resources Needed823824* Access to the `vue-email-editor` repo & `dev-example.vue`.825* Unlayer account / Project ID (if required by advanced features).826* Postgres instance & credentials.827* S3-compatible storage (bucket, keys).828* Domain for API (for CORS) and OAuth provider if SSO desired.829* Brand tokens: fonts, colors, spacing, logo assets.830831---832833834## Frontend Integration — Key Tasks8358361. **Start from `dev-example.vue`**837838 * Ensure ref access to editor (`<EmailEditor ref="editorRef" :options="editorOptions" @load="onLoad" />`).839 * Implement `onLoad` to set config, load initial design if `template.current_version` exists.840 * Expose `saveDesign`, `exportHtml`, `loadDesign` via methods bound to UI buttons.841842- One draft and one published version per template.843- Published versions are immutable.844- Merge tags scoped per org.845- Signed URLs are ephemeral and derived at read-time.846- Compiled HTML cached for current published version.847- Signed URL TTL default: 15 minutes.848- Metrics: render latency, publish latency, error rates.849850## ⚙️ Local Development Notes851852* **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.853854* **Port Consistency:** Keep the local dev server port fixed in `vite.config.ts` at:855856```ts857 server: {858 port: 9022859 }860```861862* **Network Flow / Reverse Proxy Setup:**863 External requests from outside IPs follow this path:864865```866 SSL :443 (External Request)867 ↓868 Reverse Proxy Server869 ↓870 Local Dev Server (192.168.8.137:9022)871```872873This ensures stable connections during testing and remote access, while avoiding conflicts with the agent runtime.874875876## Issues877- Review the AGENT_issues.md file for a list of current open issues.878- Use this file as the source of truth for tracking bugs, feature gaps, tech debt, and pending decisions.879880881## Resolved882- When an issue listed in AGENT_issues.md is confirmed fixed or completed, move that exact line into AGENT_resolved.md.883- 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.884- This ensures historical traceability and keeps the issues list clean while preserving context for future reference.885886---887888## 🧰 Issue Template889890### Issue [#] | [MM-DD-YYYY]891892**Title:** [Short, descriptive title of the issue]893894**Description:**895[Detailed description of the issue, how it was discovered, and any reproduction steps if relevant.]896897**Impact:**898[What part of the system is affected and how it impacts users or workflows.]899900**Status:** Open901**Priority:** [Low | Medium | High | Critical]902**Owner:** [Team or individual responsible]903**Reference:** [Optional: internal tracking ID, issue number, or ticket link]904905---906907### RESOLVED | [MM-DD-YYYY]908909**Resolution Summary:**910[Brief explanation of the fix or solution implemented.]911912**Commit:** [Commit hash or link]913**Linked PR:** [PR number or link]914**Verified By:** [QA name or date]915916---917918## ✅ Examples — Real Issue919920### Issue 1 | 10-19-2025921922**Title:** Autosave fails silently when the editor tab loses focus.923924**Description:**925Users 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.926927**Impact:**928929* Draft data can be lost unexpectedly.930* Increases user frustration and reduces trust in autosave reliability.931932**Status:** Open933**Priority:** High934**Owner:** Frontend Integration Team935**Reference:** `editor_autosave_event_bug`936937---938939940## Definition of Done941942* 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.943* All data persisted in Postgres; media stored and retrievable.944* Tests green; docs complete; lint/format pass; CI pipeline in place.945946---947
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/AGENTS.md · 0 | AGENTS.md | setupteststyletypes+8 | 49/100 | 3 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| google-gemini/gemini-cliGEMINI.md · 106k | GEMINI.md | setupbuildtestlint-format+6 | 91/100 | 3 days ago | |
| diegosouzapw/OmniRouteGEMINI.md · 39k | GEMINI.md | testlint-formatarchsecurity+2 | 87/100 | 3 days ago | |
| compozy/gographGEMINI.md · 9 | GEMINI.md | setuptestlint-formatarch+4 | 86/100 | 3 days ago | |
| nordeim/misc1/GEMINI.md · 0 | GEMINI.md | setupbuildtestlint-format+3 | 81/100 | 3 days ago | |
| firebase/flutterfireGEMINI.md · 9.2k | GEMINI.md | lint-formatstylearchdo-not+1 | 80/100 | 3 days ago | |
| nodejs/nodedeps/v8/GEMINI.md · 119k | GEMINI.md | buildteststylearch+4 | 77/100 | 3 days ago | |
| abpframework/abpnpm/ng-packs/packages/schematics/src/commands/ai-config/files/gemini/.gemini/GEMINI.md · 14k | GEMINI.md | testlint-formatstylearch+8 | 76/100 | 2 days ago | |
| zyx77550/spardaGEMINI.md · 4 | GEMINI.md | testlint-formatgitapi+2 | 75/100 | 3 days ago |
