Skip to content
This repository was archived by the owner on Oct 25, 2023. It is now read-only.

Commit 225875b

Browse files
authored
Self hosted landing page (#398)
* Landing page * Connect new landing page to sing-up functionality and use new notice page * Change demos - feedback in Slack
1 parent ce8140b commit 225875b

File tree

6 files changed

+381
-28
lines changed

6 files changed

+381
-28
lines changed

archaeologist/src/content/augmentation/SuggestionsToast.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,19 @@ function getTextToInsert(storage: StorageApi, node: TNode): string {
9595
let toInsert: string
9696
if (NodeUtil.isWebBookmark(node) && node.extattrs?.web != null) {
9797
const { web, title, author } = node.extattrs
98-
const authorStr = author ? `\nby ${author}` : ''
99-
toInsert = `${title}${authorStr}\n🧵 ${web.url} `
98+
const authorStr = author ? `, by ${author}` : ''
99+
toInsert = `${title}${authorStr}: 🧵 ${web.url} `
100100
} else if (NodeUtil.isWebQuote(node) && node.extattrs?.web_quote != null) {
101101
const { text, url } = node.extattrs.web_quote
102102
const { author } = node.extattrs
103-
const authorStr = author ? `\nby ${author}` : ''
104-
toInsert = `“${text}${authorStr}\n🧵 ${url} `
103+
const authorStr = author ? `, by ${author}` : ''
104+
toInsert = `“${text}${authorStr}: 🧵 ${url} `
105105
} else if (NodeUtil.isImage(node)) {
106106
const url = storage.blob.sourceUrl(node.nid)
107107
toInsert = ` 🧵 ${url} `
108108
} else {
109109
const doc = TDoc.fromNodeTextData(node.text)
110-
toInsert = `${doc.genPlainText()}\n🧵 ${storage.node.url(node.nid)} `
110+
toInsert = `${doc.genPlainText()}: 🧵 ${storage.node.url(node.nid)} `
111111
}
112112
return toInsert
113113
}
Lines changed: 347 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,349 @@
1-
import React from 'react'
2-
import { BuilderComponent, builder } from '@builder.io/react'
3-
4-
builder.init('0472fab3b2de47449c0ac0d0bd8d15b0')
5-
6-
// Disable builder cookies for GDPR Compliance
7-
// https://forum.builder.io/t/gdpr-compliance/292/6
8-
//
9-
// If changed, don't forget to update Cookie Policy document
10-
// legal/cookie-policy.md
11-
builder.canTrack = false
12-
13-
export const LandingPage = () => {
14-
const [builderContentJson, setBuilderContentJson] = React.useState<any>(null)
15-
React.useEffect(() => {
16-
builder
17-
.get('page', {
18-
entry: '3c6590b8ee4e4c05a67d391ed6c7b16d',
1+
/** @jsxImportSource @emotion/react */
2+
3+
import React, { useState, useRef } from 'react'
4+
import { useHistory } from 'react-router-dom'
5+
import styled from '@emotion/styled'
6+
import { Button, Form } from 'react-bootstrap'
7+
import { goto, routes } from './../lib/route'
8+
import DemoQuoteImg from './img/copy-quote-demo.png'
9+
import DemoWritingAugmentationGif from './img/mazed-demo-calendar-writing-augmentation-safes.gif'
10+
11+
import { authentication } from 'smuggler-api'
12+
import { log } from 'armoury'
13+
14+
const SlidesBox = styled.div`
15+
height: 100vh;
16+
width: 100vw;
17+
overflow: auto;
18+
scroll-snap-type: y mandatory;
19+
20+
font-family: 'Roboto', arial, sans-serif;
21+
font-size: 22px;
22+
`
23+
24+
const Slide = styled.div`
25+
width: 100vw;
26+
height: 100vh;
27+
28+
scroll-snap-align: start;
29+
`
30+
31+
const Centered = styled.div`
32+
display: flex;
33+
justify-content: center;
34+
`
35+
36+
const FirstSlideBody = styled.div`
37+
display: flex;
38+
justify-content: flex-start;
39+
height: 88vh;
40+
`
41+
const FirstSlideLeftHalf = styled.div`
42+
width: 50%;
43+
@media (max-width: 900px) {
44+
width: 100%;
45+
}
46+
47+
display: flex;
48+
justify-content: center;
49+
flex-wrap: nowrap;
50+
flex-direction: column;
51+
52+
padding: 42px;
53+
`
54+
const FirstSlideRightHalf = styled.div`
55+
width: 50%;
56+
@media (max-width: 900px) {
57+
width: 0%;
58+
display: none;
59+
}
60+
display: flex;
61+
justify-content: center;
62+
flex-wrap: nowrap;
63+
flex-direction: column;
64+
`
65+
const SecondSlideBody = styled.div`
66+
display: flex;
67+
justify-content: flex-start;
68+
padding-top: 8vh;
69+
`
70+
const SecondSlideRightHalf = styled.div`
71+
width: 50%;
72+
@media (max-width: 900px) {
73+
width: 0%;
74+
display: none;
75+
}
76+
77+
display: flex;
78+
justify-content: center;
79+
flex-wrap: nowrap;
80+
flex-direction: column;
81+
`
82+
const SecondSlideLeftHalf = styled.div`
83+
width: 50%;
84+
@media (max-width: 900px) {
85+
width: 100%;
86+
}
87+
88+
display: flex;
89+
justify-content: center;
90+
flex-wrap: nowrap;
91+
flex-direction: column;
92+
93+
padding: 42px;
94+
`
95+
const Header = styled.h1`
96+
font-size: 32px;
97+
text-align: center;
98+
`
99+
const Description = styled.h2`
100+
font-size: 18px;
101+
text-align: center;
102+
margin: 3vh 12px 0 12px;
103+
`
104+
105+
const Logo = styled.div`
106+
font-family: 'Comfortaa';
107+
font-size: 32px;
108+
`
109+
const Topbar = styled.div`
110+
display: flex;
111+
justify-content: space-between;
112+
padding: 12px;
113+
`
114+
const LoginBox = styled.div``
115+
const BtnBox = styled(Button)`
116+
background-color: white;
117+
border-color: white;
118+
`
119+
function Btn({
120+
href,
121+
children,
122+
className,
123+
}: React.PropsWithChildren<{ href: string; className?: string }>) {
124+
return (
125+
<BtnBox variant="light" href={href} className={className}>
126+
{children}
127+
</BtnBox>
128+
)
129+
}
130+
function Login() {
131+
return (
132+
<LoginBox>
133+
<Btn href={routes.login}>Log In</Btn>
134+
</LoginBox>
135+
)
136+
}
137+
const GifDemo = styled.img`
138+
width: 94%;
139+
border-color: #cecece;
140+
border-style: solid;
141+
box-shadow: 2px 2px 4px #8c8c8ceb;
142+
`
143+
const ImageDemo = styled.img`
144+
height: 86vh;
145+
border-color: #cecece;
146+
border-style: solid;
147+
box-shadow: 2px 2px 4px #8c8c8ceb;
148+
`
149+
const SignUpFormBox = styled.form`
150+
margin-top: 14vh;
151+
border-radius: 10px;
152+
width: 100%;
153+
font-size: 18px;
154+
155+
display: flex;
156+
justify-content: center;
157+
flex-wrap: nowrap;
158+
159+
@media (max-width: 480px) {
160+
flex-wrap: wrap;
161+
}
162+
`
163+
const SignUpBtn = styled(Button)`
164+
white-space: nowrap;
165+
border-radius: inherit;
166+
font-size: inherit;
167+
margin: 1em 2px 1px 1px;
168+
`
169+
const SignUpEmail = styled(Form.Control)`
170+
width: 60%;
171+
max-width: 18em;
172+
border-radius: inherit;
173+
font-size: inherit;
174+
margin: 1em 2px 1px 1px;
175+
`
176+
177+
const SignUpForm = () => {
178+
const [email, setEmail] = useState<string>('')
179+
const emailElementRef = useRef<HTMLInputElement>(null)
180+
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
181+
setEmail(event.target.value)
182+
}
183+
const history = useHistory()
184+
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
185+
event.preventDefault()
186+
authentication.user
187+
.register({
188+
name: email.split('@')[0],
189+
email: email,
190+
})
191+
.catch((err) => {
192+
log.error('User registration failed with', err)
193+
})
194+
.then((res) => {
195+
if (res) {
196+
goto.notice.youAreInWaitingList(history, {
197+
name: email.split('@')[0],
198+
email: email,
199+
})
200+
}
19201
})
20-
.promise()
21-
.then(setBuilderContentJson)
22-
}, [])
23-
return <BuilderComponent model="page" content={builderContentJson} />
202+
}
203+
return (
204+
<SignUpFormBox onSubmit={handleSubmit}>
205+
<SignUpEmail
206+
type="email"
207+
placeholder="email"
208+
onChange={onChange}
209+
value={email}
210+
ref={emailElementRef}
211+
/>
212+
<SignUpBtn
213+
variant="outline-primary"
214+
size="lg"
215+
type="submit"
216+
disabled={!emailElementRef.current?.validity.valid}
217+
>
218+
Get early access
219+
</SignUpBtn>
220+
</SignUpFormBox>
221+
)
222+
}
223+
224+
const LastSlide = styled(Slide)`
225+
position: relative;
226+
`
227+
228+
const Footer = styled.div`
229+
width: 100%;
230+
position: absolute;
231+
bottom: 0;
232+
display: flex;
233+
flex-wrap: wrap;
234+
align-content: space-around;
235+
justify-content: center;
236+
padding: 16px;
237+
`
238+
239+
const FooterCol = styled.div`
240+
text-align: left;
241+
width: 250px;
242+
`
243+
const FooterItem = styled.div`
244+
font-sixe: 16px;
245+
`
246+
247+
const TextStrikeThrough = styled.span`
248+
text-decoration: line-through;
249+
text-decoration-color: blue;
250+
`
251+
const TextHighlight = styled.span`
252+
font-weight: 900;
253+
color: blue;
254+
`
255+
256+
export function LandingPage() {
257+
return (
258+
<SlidesBox>
259+
<Slide>
260+
<Topbar>
261+
<Logo>🧵 Mazed</Logo>
262+
<Login />
263+
</Topbar>
264+
<FirstSlideBody>
265+
<FirstSlideLeftHalf>
266+
<Header>
267+
<div>Share any page you've read.</div>
268+
<div>
269+
<b>Without searching for it.</b>
270+
</div>
271+
</Header>
272+
<Description>
273+
Mazed is a browser extension that saves the pages you view
274+
automatically, and resurfaces them to you when you need it. Your
275+
memory, at your fingertips.
276+
</Description>
277+
<SignUpForm />
278+
</FirstSlideLeftHalf>
279+
<FirstSlideRightHalf>
280+
<Centered>
281+
<GifDemo src={DemoWritingAugmentationGif} />
282+
</Centered>
283+
</FirstSlideRightHalf>
284+
</FirstSlideBody>
285+
</Slide>
286+
<Slide>
287+
<SecondSlideBody>
288+
<SecondSlideRightHalf>
289+
<Centered>
290+
<ImageDemo src={DemoQuoteImg} />
291+
</Centered>
292+
</SecondSlideRightHalf>
293+
<SecondSlideLeftHalf>
294+
<Header>
295+
<TextStrikeThrough>Find </TextStrikeThrough>
296+
<TextHighlight>Have</TextHighlight> what you need.
297+
</Header>
298+
<Description>
299+
The article, page, or google doc you need is just a click away.
300+
Mazed will suggest the relevant pages from your history to you, as
301+
you type.
302+
</Description>
303+
</SecondSlideLeftHalf>
304+
</SecondSlideBody>
305+
</Slide>
306+
<LastSlide>
307+
<Centered>
308+
<SignUpForm />
309+
</Centered>
310+
<Footer>
311+
<FooterCol>
312+
<Logo>Mazed</Logo>
313+
</FooterCol>
314+
<FooterCol>
315+
<FooterItem>
316+
<Btn href={routes.login}>Log In</Btn>
317+
</FooterItem>
318+
<FooterItem>
319+
<Btn
320+
href={
321+
'https://chrome.google.com/webstore/detail/mazed/hkfjmbjendcoblcoackpapfphijagddc'
322+
}
323+
>
324+
Download
325+
</Btn>
326+
</FooterItem>
327+
<FooterItem>
328+
<Btn href={routes.terms}>Terms and Conditions</Btn>
329+
</FooterItem>
330+
<FooterItem>
331+
<Btn href={routes.privacy}>Privacy Policy</Btn>
332+
</FooterItem>
333+
<FooterItem>
334+
<Btn href={routes.cookiePolicy}>Cookie Policy</Btn>
335+
</FooterItem>
336+
</FooterCol>
337+
<FooterCol>
338+
<FooterItem>
339+
<Btn href={'https://mazed.se'}>mazed.se</Btn>
340+
</FooterItem>
341+
<FooterItem>
342+
<Btn href={'mailto: mazed@fastmail.com'}>mazed@fastmail.com</Btn>
343+
</FooterItem>
344+
</FooterCol>
345+
</Footer>
346+
</LastSlide>
347+
</SlidesBox>
348+
)
24349
}
Loading
Loading

0 commit comments

Comments
 (0)