KSvend Claude Happy commited on
Commit
73b5679
·
1 Parent(s): ae74af5

rebrand: apply full MERLx Aperture identity per design spec

Browse files

Updates all user-facing copy (landing page, PDF reports, emails, README)
and backend metadata to use "MERLx Aperture" branding consistently,
per the approved 2026-03-26 rebrand design specification.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>

README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Aperture
3
  emoji: 🛰️
4
  colorFrom: green
5
  colorTo: blue
@@ -7,6 +7,8 @@ sdk: docker
7
  app_port: 7860
8
  ---
9
 
10
- # Aperture
11
 
12
- Satellite intelligence for humanitarian programme teams. Built by MERLx.
 
 
 
1
  ---
2
+ title: MERLx Aperture
3
  emoji: 🛰️
4
  colorFrom: green
5
  colorTo: blue
 
7
  app_port: 7860
8
  ---
9
 
10
+ # MERLx Aperture
11
 
12
+ AI-enhanced satellite analysis for humanitarian programme teams. Part of the MERLx Optics Suite.
13
+
14
+ Built on methods developed in the SR4S research project.
app/core/email.py CHANGED
@@ -6,7 +6,7 @@ import httpx
6
  logger = logging.getLogger(__name__)
7
 
8
  RESEND_API_KEY = os.environ.get("RESEND_API_KEY", "")
9
- FROM_EMAIL = "Aperture <noreply@aperture.merlx.org>"
10
 
11
  async def send_completion_email(to_email: str, job_id: str, aoi_name: str) -> bool:
12
  if not RESEND_API_KEY:
@@ -21,7 +21,7 @@ async def send_completion_email(to_email: str, job_id: str, aoi_name: str) -> bo
21
  The satellite analysis for <strong>{aoi_name}</strong> is complete.
22
  </p>
23
  <p style="font-size: 11px; color: #6B6B6B; margin-top: 20px;">
24
- Generated by Aperture (MERLx) using open satellite data.
25
  </p>
26
  </div>
27
  """
@@ -30,6 +30,6 @@ async def send_completion_email(to_email: str, job_id: str, aoi_name: str) -> bo
30
  resp = await client.post(
31
  "https://api.resend.com/emails",
32
  headers={"Authorization": f"Bearer {RESEND_API_KEY}"},
33
- json={"from": FROM_EMAIL, "to": [to_email], "subject": f"Aperture: Analysis ready — {aoi_name}", "html": html},
34
  )
35
  return resp.status_code == 200
 
6
  logger = logging.getLogger(__name__)
7
 
8
  RESEND_API_KEY = os.environ.get("RESEND_API_KEY", "")
9
+ FROM_EMAIL = "MERLx Aperture <noreply@aperture.merlx.org>"
10
 
11
  async def send_completion_email(to_email: str, job_id: str, aoi_name: str) -> bool:
12
  if not RESEND_API_KEY:
 
21
  The satellite analysis for <strong>{aoi_name}</strong> is complete.
22
  </p>
23
  <p style="font-size: 11px; color: #6B6B6B; margin-top: 20px;">
24
+ Generated by MERLx Aperture using open satellite data.
25
  </p>
26
  </div>
27
  """
 
30
  resp = await client.post(
31
  "https://api.resend.com/emails",
32
  headers={"Authorization": f"Bearer {RESEND_API_KEY}"},
33
+ json={"from": FROM_EMAIL, "to": [to_email], "subject": f"MERLx Aperture: Analysis ready — {aoi_name}", "html": html},
34
  )
35
  return resp.status_code == 200
app/main.py CHANGED
@@ -30,7 +30,7 @@ def create_app(db_path: str = "aperture.db", run_worker: bool = False) -> FastAP
30
  if worker_task is not None:
31
  worker_task.cancel()
32
 
33
- app = FastAPI(title="Aperture", lifespan=lifespan)
34
  init_jobs(db)
35
  app.include_router(jobs_router)
36
  app.include_router(indicators_router)
@@ -77,7 +77,7 @@ def create_app(db_path: str = "aperture.db", run_worker: bool = False) -> FastAP
77
  async def serve_index():
78
  if _INDEX_HTML.exists():
79
  return HTMLResponse(content=_INDEX_HTML.read_text(encoding="utf-8"))
80
- return HTMLResponse(content="<h1>Aperture</h1><p>Frontend not found.</p>")
81
 
82
  return app
83
 
 
30
  if worker_task is not None:
31
  worker_task.cancel()
32
 
33
+ app = FastAPI(title="MERLx Aperture", lifespan=lifespan)
34
  init_jobs(db)
35
  app.include_router(jobs_router)
36
  app.include_router(indicators_router)
 
77
  async def serve_index():
78
  if _INDEX_HTML.exists():
79
  return HTMLResponse(content=_INDEX_HTML.read_text(encoding="utf-8"))
80
+ return HTMLResponse(content="<h1>MERLx Aperture</h1><p>Frontend not found.</p>")
81
 
82
  return app
83
 
app/outputs/report.py CHANGED
@@ -229,7 +229,7 @@ def generate_pdf_report(
229
  canvas.setFont("Helvetica", 7)
230
  canvas.setFillColor(INK_MUTED)
231
  footer_text = (
232
- f"Aperture Situation Report \u2014 {aoi.name} \u2014 "
233
  f"{time_range.start} to {time_range.end} \u2014 "
234
  f"Page {doc.page}"
235
  )
@@ -242,8 +242,8 @@ def generate_pdf_report(
242
  output_path,
243
  pagesize=A4,
244
  pageTemplates=[template],
245
- title=f"Aperture Report — {aoi.name}",
246
- author="Aperture (MERLx)",
247
  )
248
  doc.pageBackgrounds = [colors.white]
249
 
@@ -255,7 +255,7 @@ def generate_pdf_report(
255
  from datetime import datetime as _dt, timezone as _tz
256
  generated_at = _dt.now(_tz.utc).strftime("%Y-%m-%d %H:%M UTC")
257
 
258
- story.append(Paragraph("Aperture Situation Report", styles["title"]))
259
  story.append(Paragraph(aoi.name, styles["subtitle"]))
260
  story.append(
261
  Paragraph(
@@ -397,10 +397,10 @@ def generate_pdf_report(
397
  story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#D8D5CF")))
398
  story.append(Spacer(1, 3 * mm))
399
  disclaimer = (
400
- "This report has been generated automatically by the Aperture platform using satellite "
401
  "remote sensing data. Results are intended to support humanitarian situation analysis "
402
  "and should be interpreted alongside ground-truth information and expert judgement. "
403
- "Aperture makes no warranty as to the accuracy or completeness of the data presented. "
404
  "All indicators are based on open-source satellite imagery and publicly available "
405
  "geospatial datasets. Temporal coverage, cloud contamination, and sensor resolution "
406
  "may affect the reliability of individual indicators. Users are encouraged to review "
 
229
  canvas.setFont("Helvetica", 7)
230
  canvas.setFillColor(INK_MUTED)
231
  footer_text = (
232
+ f"MERLx Aperture \u2014 Situation Report \u2014 {aoi.name} \u2014 "
233
  f"{time_range.start} to {time_range.end} \u2014 "
234
  f"Page {doc.page}"
235
  )
 
242
  output_path,
243
  pagesize=A4,
244
  pageTemplates=[template],
245
+ title=f"MERLx Aperture — Situation Report — {aoi.name}",
246
+ author="MERLx Aperture",
247
  )
248
  doc.pageBackgrounds = [colors.white]
249
 
 
255
  from datetime import datetime as _dt, timezone as _tz
256
  generated_at = _dt.now(_tz.utc).strftime("%Y-%m-%d %H:%M UTC")
257
 
258
+ story.append(Paragraph("MERLx Aperture Situation Report", styles["title"]))
259
  story.append(Paragraph(aoi.name, styles["subtitle"]))
260
  story.append(
261
  Paragraph(
 
397
  story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#D8D5CF")))
398
  story.append(Spacer(1, 3 * mm))
399
  disclaimer = (
400
+ "This report has been generated automatically by MERLx Aperture using satellite "
401
  "remote sensing data. Results are intended to support humanitarian situation analysis "
402
  "and should be interpreted alongside ground-truth information and expert judgement. "
403
+ "MERLx Aperture makes no warranty as to the accuracy or completeness of the data presented. "
404
  "All indicators are based on open-source satellite imagery and publicly available "
405
  "geospatial datasets. Temporal coverage, cloud contamination, and sensor resolution "
406
  "may affect the reliability of individual indicators. Users are encouraged to review "
frontend/index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Aperture</title>
7
 
8
  <!-- MERLx Design System -->
9
  <link rel="stylesheet" href="/static/css/merlx.css" />
@@ -86,15 +86,20 @@
86
  MERL<span style="color: var(--iris)">x</span>
87
  </div>
88
 
 
 
 
 
 
89
  <!-- Headline -->
90
  <h1 class="landing-headline">
91
- Satellite intelligence for programme teams.
92
  </h1>
93
 
94
  <!-- Sub-copy -->
95
  <p class="landing-sub">
96
- Upload your area of interest, choose indicators, and receive
97
- a ready-made report backed by Sentinel-2 imagery within minutes.
98
  </p>
99
 
100
  <!-- CTA -->
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>MERLx Aperture</title>
7
 
8
  <!-- MERLx Design System -->
9
  <link rel="stylesheet" href="/static/css/merlx.css" />
 
86
  MERL<span style="color: var(--iris)">x</span>
87
  </div>
88
 
89
+ <!-- Subtitle -->
90
+ <div class="landing-subtitle" style="font-family: 'DM Serif Display', serif; font-style: italic; font-size: var(--text-lg); color: var(--ink-muted); margin-top: var(--space-3);">
91
+ Aperture
92
+ </div>
93
+
94
  <!-- Headline -->
95
  <h1 class="landing-headline">
96
+ AI-enhanced satellite analysis for humanitarian programme teams.
97
  </h1>
98
 
99
  <!-- Sub-copy -->
100
  <p class="landing-sub">
101
+ Draw your area, choose your indicators, get evidence-grade
102
+ satellite analysis delivered using free, open data.
103
  </p>
104
 
105
  <!-- CTA -->
pyproject.toml CHANGED
@@ -1,7 +1,7 @@
1
  [project]
2
  name = "aperture"
3
  version = "0.1.0"
4
- description = "Satellite intelligence platform for humanitarian programme teams"
5
  requires-python = ">=3.11"
6
  dependencies = [
7
  "fastapi>=0.110.0",
 
1
  [project]
2
  name = "aperture"
3
  version = "0.1.0"
4
+ description = "MERLx Aperture AI-enhanced satellite analysis for humanitarian programme teams"
5
  requires-python = ">=3.11"
6
  dependencies = [
7
  "fastapi>=0.110.0",