History

Add Google OAuth homepage (#1635)

Rhys Sullivan committed 2 months ago

Commit f5fffae1 parent 194ef261 file · +512 −0Browse files

Unified · Split

apps/marketing/src/pages/google-oauth.astro+512−0
@@ -0,0 +1,512 @@
1---
2import Layout from "../layouts/Layout.astro";
3
4const googleServices = [
5 {
6 index: "01",
7 name: "Google Calendar",
8 purpose:
9 "Executor can read your calendars and events, then create, update, or remove events when you ask an agent to manage your schedule.",
10 scope: "googleapis.com/auth/calendar",
11 },
12 {
13 index: "02",
14 name: "Gmail",
15 purpose:
16 "Executor can read, search, compose, send, label, archive, and move messages to trash when you instruct an agent to work with your email.",
17 scope: "googleapis.com/auth/gmail.modify",
18 },
19 {
20 index: "03",
21 name: "Google Sheets",
22 purpose:
23 "Executor can read spreadsheet data and update cells, ranges, and worksheets when you ask an agent to work with a spreadsheet.",
24 scope: "googleapis.com/auth/spreadsheets",
25 },
26] as const;
27---
28
29<Layout
30 title="Executor"
31 description="How Executor connects AI agents to Google Calendar, Gmail, and Google Sheets with your permission."
32>
33 <main class="google-page">
34 <div class="grid-field" aria-hidden="true"></div>
35
36 <nav class="site-nav" aria-label="Primary navigation">
37 <div class="shell nav-inner">
38 <a href="/" class="brand" aria-label="Executor home">
39 <img src="/favicon-192.png" alt="" width="20" height="20" />
40 <span>executor</span>
41 </a>
42 <div class="nav-links">
43 <a href="https://executor.sh/privacy">Privacy</a>
44 <a href="https://executor.sh/terms">Terms</a>
45 <a href="/api/auth/login" class="nav-cta">Open Executor <span aria-hidden="true">→</span></a>
46 </div>
47 </div>
48 </nav>
49
50 <header class="shell hero">
51 <div class="eyebrow">
52 <span class="google-mark" aria-hidden="true">
53 <i></i><i></i><i></i><i></i>
54 </span>
55 Google Workspace connections
56 </div>
57 <h1>Executor</h1>
58 <p class="hero-copy">
59 Executor is an integration platform and MCP gateway for AI agents. It lets you
60 securely connect Google Calendar, Gmail, and Google Sheets so an agent can read
61 data and take the actions <em>you request</em>.
62 </p>
63 <div class="hero-rule">
64 <span>One connection</span>
65 <span>Explicit permission</span>
66 <span>User-directed actions</span>
67 </div>
68 </header>
69
70 <section class="shell ledger" aria-labelledby="google-data-heading">
71 <div class="section-intro">
72 <p class="section-number">01 / Google data</p>
73 <div>
74 <h2 id="google-data-heading">What Executor accesses—and why</h2>
75 <p>
76 You choose which Google service to connect. Executor requests only the
77 permissions needed for that connection and uses them to carry out your
78 instructions.
79 </p>
80 </div>
81 </div>
82
83 <div class="service-list">
84 {
85 googleServices.map((service) => (
86 <article class="service-row">
87 <div class="service-index">{service.index}</div>
88 <div class="service-body">
89 <h3>{service.name}</h3>
90 <p>{service.purpose}</p>
91 </div>
92 <code>{service.scope}</code>
93 </article>
94 ))
95 }
96 </div>
97 </section>
98
99 <section class="shell control" aria-labelledby="control-heading">
100 <div class="section-intro">
101 <p class="section-number">02 / Your control</p>
102 <div>
103 <h2 id="control-heading">Your Google account stays yours</h2>
104 <p>
105 Connecting Google does not give Executor permission to act on its own. An
106 agent can use a Google tool only when you direct it to, subject to the
107 policies and approvals you configure in Executor.
108 </p>
109 </div>
110 </div>
111
112 <div class="control-grid">
113 <article>
114 <span class="control-glyph" aria-hidden="true">↗</span>
115 <h3>See the action</h3>
116 <p>Executor exposes concrete Google actions with their inputs, not an open-ended account session.</p>
117 </article>
118 <article>
119 <span class="control-glyph" aria-hidden="true">◇</span>
120 <h3>Set the policy</h3>
121 <p>Allow an action, require approval, or block it before an agent can run it.</p>
122 </article>
123 <article>
124 <span class="control-glyph" aria-hidden="true">×</span>
125 <h3>Revoke access</h3>
126 <p>
127 Remove the connection in Executor or revoke it from your
128 <a href="https://myaccount.google.com/permissions">Google Account permissions</a>.
129 </p>
130 </article>
131 </div>
132 </section>
133
134 <section class="shell disclosure" aria-labelledby="privacy-heading">
135 <p class="section-number">03 / Privacy</p>
136 <div class="disclosure-card">
137 <div>
138 <h2 id="privacy-heading">Clear limits on Google data</h2>
139 <p>
140 Executor does not sell Google user data. We use Google data only to provide
141 and improve the user-facing integration features you request, in accordance
142 with our Privacy Policy. Executor's use and transfer of information received
143 from Google APIs adheres to the
144 <a href="https://developers.google.com/terms/api-services-user-data-policy"
145 >Google API Services User Data Policy</a
146 >, including the Limited Use requirements.
147 </p>
148 </div>
149 <div class="policy-links">
150 <a href="https://executor.sh/privacy">Read the Privacy Policy <span aria-hidden="true">↗</span></a>
151 <a href="https://executor.sh/terms">Read the Terms of Service <span aria-hidden="true">↗</span></a>
152 </div>
153 </div>
154 </section>
155
156 <footer class="site-footer">
157 <div class="shell footer-inner">
158 <span>Executor · Useful Software Company</span>
159 <span>Google access, explained plainly.</span>
160 </div>
161 </footer>
162 </main>
163</Layout>
164
165<style>
166 .google-page {
167 --google-blue: #4285f4;
168 --google-red: #ea4335;
169 --google-yellow: #fbbc04;
170 --google-green: #34a853;
171 position: relative;
172 min-height: 100dvh;
173 overflow: hidden;
174 background: var(--color-surface);
175 color: var(--color-ink);
176 }
177
178 .grid-field {
179 position: absolute;
180 inset: 0 0 auto;
181 height: 48rem;
182 pointer-events: none;
183 opacity: 0.38;
184 background-image:
185 linear-gradient(to right, var(--color-rule) 1px, transparent 1px),
186 linear-gradient(to bottom, var(--color-rule) 1px, transparent 1px);
187 background-size: 32px 32px;
188 mask-image: linear-gradient(to bottom, #000 0%, transparent 88%);
189 }
190
191 .shell {
192 position: relative;
193 z-index: 1;
194 width: min(1120px, calc(100% - 3rem));
195 margin-inline: auto;
196 }
197
198 .site-nav {
199 position: relative;
200 z-index: 2;
201 border-bottom: 1px solid var(--color-rule);
202 background: color-mix(in srgb, var(--color-surface) 88%, transparent);
203 backdrop-filter: blur(16px);
204 }
205
206 .nav-inner,
207 .footer-inner {
208 display: flex;
209 min-height: 3.5rem;
210 align-items: center;
211 justify-content: space-between;
212 }
213
214 .brand {
215 display: inline-flex;
216 align-items: center;
217 gap: 0.65rem;
218 color: var(--color-ink);
219 font-size: 0.95rem;
220 font-weight: 600;
221 letter-spacing: -0.01em;
222 text-decoration: none;
223 }
224
225 .nav-links {
226 display: flex;
227 align-items: center;
228 gap: 1.4rem;
229 font-size: 0.82rem;
230 }
231
232 .nav-links a {
233 color: var(--color-ink-2);
234 text-decoration: none;
235 }
236
237 .nav-links a:hover {
238 color: var(--color-ink);
239 }
240
241 .nav-links .nav-cta {
242 padding: 0.55rem 0.8rem;
243 border: 1px solid var(--color-ink);
244 border-radius: 0.2rem;
245 color: var(--color-surface);
246 background: var(--color-ink);
247 }
248
249 .hero {
250 padding-block: clamp(6rem, 14vw, 10rem) clamp(5rem, 10vw, 8rem);
251 }
252
253 .eyebrow,
254 .section-number {
255 display: flex;
256 align-items: center;
257 gap: 0.75rem;
258 margin: 0;
259 color: var(--color-ink-2);
260 font-family: var(--font-mono);
261 font-size: 0.7rem;
262 letter-spacing: 0.13em;
263 text-transform: uppercase;
264 }
265
266 .google-mark {
267 display: grid;
268 grid-template-columns: repeat(4, 0.45rem);
269 gap: 0.16rem;
270 }
271
272 .google-mark i {
273 width: 0.45rem;
274 height: 0.45rem;
275 border-radius: 50%;
276 background: var(--google-blue);
277 }
278
279 .google-mark i:nth-child(2) { background: var(--google-red); }
280 .google-mark i:nth-child(3) { background: var(--google-yellow); }
281 .google-mark i:nth-child(4) { background: var(--google-green); }
282
283 .hero h1 {
284 margin: 1.8rem 0 1.5rem;
285 font-family: var(--font-display);
286 font-size: clamp(5rem, 17vw, 11rem);
287 font-weight: 600;
288 letter-spacing: -0.065em;
289 line-height: 0.78;
290 }
291
292 .hero-copy {
293 max-width: 48rem;
294 margin: 0;
295 color: var(--color-ink-2);
296 font-size: clamp(1.15rem, 2.5vw, 1.65rem);
297 line-height: 1.55;
298 }
299
300 .hero-copy em {
301 color: var(--color-ink);
302 font-family: var(--font-serif);
303 font-weight: 500;
304 }
305
306 .hero-rule {
307 display: grid;
308 grid-template-columns: repeat(3, 1fr);
309 margin-top: 4rem;
310 border-block: 1px solid var(--color-rule);
311 color: var(--color-ink-2);
312 font-family: var(--font-mono);
313 font-size: 0.69rem;
314 letter-spacing: 0.09em;
315 text-transform: uppercase;
316 }
317
318 .hero-rule span {
319 padding: 1rem 1.1rem;
320 border-right: 1px solid var(--color-rule);
321 }
322
323 .hero-rule span:first-child { padding-left: 0; }
324 .hero-rule span:last-child { border-right: 0; }
325
326 .ledger,
327 .control,
328 .disclosure {
329 padding-block: clamp(4.5rem, 9vw, 7rem);
330 border-top: 1px solid var(--color-rule);
331 }
332
333 .section-intro {
334 display: grid;
335 grid-template-columns: minmax(9rem, 0.45fr) minmax(0, 1fr);
336 gap: 3rem;
337 }
338
339 .section-intro h2,
340 .disclosure-card h2 {
341 max-width: 14ch;
342 margin: 0;
343 font-family: var(--font-display);
344 font-size: clamp(2.2rem, 5vw, 4.2rem);
345 font-weight: 550;
346 letter-spacing: -0.04em;
347 line-height: 0.98;
348 }
349
350 .section-intro > div > p,
351 .disclosure-card > div > p {
352 max-width: 42rem;
353 margin: 1.5rem 0 0;
354 color: var(--color-ink-2);
355 font-size: 1rem;
356 line-height: 1.75;
357 }
358
359 .service-list {
360 margin-top: 4rem;
361 border-top: 1px solid var(--color-ink);
362 }
363
364 .service-row {
365 display: grid;
366 grid-template-columns: 5rem minmax(0, 1fr) minmax(14rem, 0.5fr);
367 gap: 2rem;
368 align-items: start;
369 padding-block: 2.2rem;
370 border-bottom: 1px solid var(--color-rule);
371 }
372
373 .service-index,
374 .service-row code {
375 color: var(--color-ink-3);
376 font-family: var(--font-mono);
377 font-size: 0.68rem;
378 }
379
380 .service-body h3 {
381 margin: 0 0 0.65rem;
382 font-size: 1.15rem;
383 font-weight: 600;
384 letter-spacing: -0.02em;
385 }
386
387 .service-body p {
388 max-width: 39rem;
389 margin: 0;
390 color: var(--color-ink-2);
391 font-size: 0.92rem;
392 line-height: 1.7;
393 }
394
395 .service-row code {
396 overflow-wrap: anywhere;
397 line-height: 1.6;
398 }
399
400 .control-grid {
401 display: grid;
402 grid-template-columns: repeat(3, 1fr);
403 margin-top: 4rem;
404 border: 1px solid var(--color-rule);
405 }
406
407 .control-grid article {
408 min-height: 18rem;
409 padding: 2rem;
410 border-right: 1px solid var(--color-rule);
411 }
412
413 .control-grid article:last-child { border-right: 0; }
414
415 .control-glyph {
416 display: block;
417 margin-bottom: 4rem;
418 font-family: var(--font-serif);
419 font-size: 1.6rem;
420 }
421
422 .control-grid h3 {
423 margin: 0 0 0.7rem;
424 font-size: 1rem;
425 }
426
427 .control-grid p {
428 margin: 0;
429 color: var(--color-ink-2);
430 font-size: 0.88rem;
431 line-height: 1.7;
432 }
433
434 .control-grid a {
435 color: var(--color-ink);
436 text-underline-offset: 0.2em;
437 }
438
439 .disclosure-card {
440 display: grid;
441 grid-template-columns: minmax(0, 1fr) minmax(16rem, 0.48fr);
442 gap: 4rem;
443 margin-top: 2.2rem;
444 padding: clamp(2rem, 5vw, 4rem);
445 background: var(--color-ink);
446 color: var(--color-surface);
447 }
448
449 .disclosure-card h2 { max-width: 12ch; }
450 .disclosure-card > div > p { color: color-mix(in srgb, var(--color-surface) 70%, transparent); }
451 .disclosure-card > div > p a {
452 color: var(--color-surface);
453 text-underline-offset: 0.2em;
454 }
455
456 .policy-links {
457 display: flex;
458 flex-direction: column;
459 align-self: end;
460 border-top: 1px solid color-mix(in srgb, var(--color-surface) 24%, transparent);
461 }
462
463 .policy-links a {
464 display: flex;
465 justify-content: space-between;
466 padding-block: 1rem;
467 border-bottom: 1px solid color-mix(in srgb, var(--color-surface) 24%, transparent);
468 color: var(--color-surface);
469 font-size: 0.82rem;
470 text-decoration: none;
471 }
472
473 .site-footer {
474 border-top: 1px solid var(--color-rule);
475 }
476
477 .footer-inner {
478 min-height: 6rem;
479 color: var(--color-ink-3);
480 font-family: var(--font-mono);
481 font-size: 0.68rem;
482 letter-spacing: 0.04em;
483 }
484
485 @media (max-width: 760px) {
486 .shell { width: min(100% - 2rem, 1120px); }
487 .nav-links > a:not(.nav-cta) { display: none; }
488 .hero { padding-top: 5rem; }
489 .hero h1 { font-size: clamp(4.2rem, 23vw, 7rem); }
490 .hero-rule { grid-template-columns: 1fr; }
491 .hero-rule span,
492 .hero-rule span:first-child {
493 padding: 0.75rem 0;
494 border-right: 0;
495 border-bottom: 1px solid var(--color-rule);
496 }
497 .hero-rule span:last-child { border-bottom: 0; }
498 .section-intro,
499 .disclosure-card { grid-template-columns: 1fr; gap: 2rem; }
500 .service-row { grid-template-columns: 2.5rem 1fr; gap: 1rem; }
501 .service-row code { grid-column: 2; }
502 .control-grid { grid-template-columns: 1fr; }
503 .control-grid article {
504 min-height: auto;
505 border-right: 0;
506 border-bottom: 1px solid var(--color-rule);
507 }
508 .control-grid article:last-child { border-bottom: 0; }
509 .control-glyph { margin-bottom: 2.5rem; }
510 .footer-inner { align-items: flex-start; flex-direction: column; justify-content: center; gap: 0.45rem; }
511 }
512</style>