Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mastodon
GitHub Repository: mastodon/joinmastodon
Path: blob/main/pages/branding.tsx
1006 views
1
import BasicPage from "../components/BasicPage"
2
import Head from "next/head"
3
import Hero from "../components/Hero"
4
import { withDefaultStaticProps } from "../utils/defaultStaticProps"
5
import classNames from "classnames"
6
import Layout from "../components/Layout"
7
import heroImage from "../public/illustrations/apps_hero_desktop.png"
8
import Image from "next/legacy/image"
9
import colors from "../data/colors"
10
11
import screenshotComposeLight from "../public/screenshots/android/Compose-0b1ddc94-d84d-4376-b957-9f676e851964.png"
12
import screenshotHomeLight from "../public/screenshots/android/HomeTimeline-add072f5-fb82-41d6-a1b1-b42707d46cac.png"
13
import screenshotProfileLight from "../public/screenshots/android/Profile-1a3889e8-43a3-4607-88cf-448ace95859a.png"
14
import screenshotServerRulesLight from "../public/screenshots/android/InstanceRules-99b01960-0551-4f26-bd69-eee3c0d9bcf5.png"
15
import screenshotThreadLight from "../public/screenshots/android/Thread-e4976e5a-7766-4ffa-bab1-7e26f54cf47c.png"
16
17
import CheckIcon from "../public/icons/check.svg?inline"
18
import LogoPurple from "../public/logos/logo-purple.svg?inline"
19
import WordmarkWhiteText from "../public/logos/wordmark-white-text.svg?inline"
20
21
const BrandSection = ({
22
title,
23
copy,
24
ctas,
25
preview,
26
}: {
27
title: React.ReactNode | string
28
copy?: React.ReactNode
29
ctas?: React.ReactNode
30
preview: React.ReactNode
31
}) => (
32
<section className="col-span-12 grid gap-16 text-center md:col-start-3 md:col-end-11">
33
<div className="full-width-bg">
34
<div className="full-width-bg__inner flex flex-col items-center justify-center pt-20">
35
<h2 className="h3 max-w-[17ch]">{title}</h2>
36
{copy && (
37
<div className="b1 mt-2 flex max-w-[50ch] flex-col gap-8">{copy}</div>
38
)}
39
{ctas && <div className="mt-12 flex justify-center gap-12">{ctas}</div>}
40
</div>
41
</div>
42
{preview}
43
</section>
44
)
45
46
const Logo = ({
47
label,
48
src,
49
className,
50
}: {
51
label: string
52
src: string
53
className?: string
54
}) => (
55
<div className="flex items-center justify-center rounded-md">
56
<a
57
download
58
title={label}
59
href={src}
60
className={classNames(
61
"flex h-full w-full items-center justify-center rounded-md transition-colors",
62
className
63
)}
64
>
65
<div className="md:h-18 relative h-16 w-full lg:h-20">
66
<Image src={src} alt="" layout="fill" />
67
</div>
68
</a>
69
</div>
70
)
71
72
const UsageRule = ({ text }: { text: string }) => {
73
return (
74
<div className="flex items-center gap-6 text-left">
75
<CheckIcon className="shrink-0 fill-blurple-500" />
76
<p>{text}</p>
77
</div>
78
)
79
}
80
81
/** This page does not require translations */
82
const Branding = () => (
83
<Layout>
84
<div dir="ltr" className="[unicode-bidi:plaintext]">
85
<Hero desktopImage={heroImage} mobileImage={heroImage}>
86
<h1 className="h1 mb-8 pt-16">Brand Toolkit</h1>
87
<p className="sh1">
88
Learn our branding guidelines, download our logos and icons, or use
89
our brand colors for&nbsp;your&nbsp;projects.
90
</p>
91
</Hero>
92
<div className="grid grid-cols-12 gap-gutter">
93
<BrandSection
94
title="Wordmark"
95
copy={
96
<p>
97
We take pride in the Mastodon logo and hope you do too.
98
Please&nbsp;take a moment to think about how you apply it. If you
99
want to use our art, please keep it tasteful!
100
</p>
101
}
102
preview={
103
<>
104
{[
105
{
106
label: "Download the SVG wordmark with white text",
107
src: "/logos/wordmark-white-text.svg",
108
styles: "bg-eggplant hocus:bg-black p-16",
109
},
110
{
111
label: "Download the SVG wordmark with black text",
112
src: "/logos/wordmark-black-text.svg",
113
styles: "bg-white hocus:bg-gray-5 p-16",
114
},
115
].map((image) => (
116
<Logo
117
key={image.src}
118
src={image.src}
119
label={image.label}
120
className={image.styles}
121
/>
122
))}
123
124
<UsageRule text="Use the main logo (black or white version) on a background that creates enough contrast to retain logo quality" />
125
126
{[
127
{
128
label:
129
"Download the SVG wordmark with a white logo and black text",
130
src: "/logos/logo-full-black.svg",
131
styles: "bg-blurple-500 hocus:bg-blurple-600 p-16",
132
},
133
{
134
label:
135
"Download the SVG wordmark with a black logo and white text",
136
src: "/logos/logo-full-white.svg",
137
styles: "bg-blurple-500 hocus:bg-blurple-600 p-16",
138
},
139
].map((image) => (
140
<Logo
141
key={image.src}
142
src={image.src}
143
label={image.label}
144
className={image.styles}
145
/>
146
))}
147
148
<UsageRule text="Use a black or white version of the logo when contrast can not be maintained with the main logo — for example above, using the main brand color for a background" />
149
</>
150
}
151
/>
152
153
<BrandSection
154
title="Mark only"
155
copy={
156
<p>
157
Use these only when the Mastodon brand has been clearly
158
established in the design.
159
</p>
160
}
161
preview={
162
<>
163
<div className="grid grid-cols-3 gap-gutter md:px-8 lg:gap-24">
164
{[
165
{
166
label: "Download the purple SVG logo",
167
src: "/logos/logo-purple.svg",
168
styles: "bg-white hocus:bg-gray-5 p-4 aspect-square",
169
},
170
{
171
label: "Download the black SVG logo",
172
src: "/logos/logo-black.svg",
173
styles: "bg-white hocus:bg-gray-5 p-4 aspect-square",
174
},
175
{
176
label: "Download the white SVG logo",
177
src: "/logos/logo-white.svg",
178
styles: "bg-black hocus:bg-gray-0 p-4 aspect-square",
179
},
180
].map((image) => (
181
<Logo
182
key={image.src}
183
src={image.src}
184
label={image.label}
185
className={image.styles}
186
/>
187
))}
188
</div>
189
<UsageRule text="Use the small version of the logo when the brand has already been established and / or space is limited to allow appropriate clear space around the main Mastodon logo" />
190
<UsageRule text="Use the one color black or white version of the logo in applications of print or letterhead when only one print color is available" />
191
</>
192
}
193
/>
194
195
<BrandSection
196
title="Clear space"
197
copy={
198
<p>
199
When using our logo, please ensure that you give it room to
200
breathe! At least 36px on all sides please.
201
</p>
202
}
203
preview={
204
<div className="flex flex-col items-center justify-center gap-4 overflow-hidden sm:flex-row md:gap-32">
205
{[LogoPurple, WordmarkWhiteText].map((Svg, i) => (
206
<div
207
className="relative rounded bg-eggplant p-[36px] text-blurple-600 shadow-[currentColor_0_0_0_1px_inset]"
208
key={i}
209
>
210
{/* everything except for the image is a guide mark */}
211
<div className="absolute top-0 left-0 h-[36px] w-[36px] rounded-full border" />
212
<div className="absolute top-0 right-0 h-[36px] w-[36px] rounded-full border" />
213
<div className="absolute bottom-0 left-0 h-[36px] w-[36px] rounded-full border" />
214
<div className="absolute bottom-0 right-0 h-[36px] w-[36px] rounded-full border" />
215
<div className="absolute top-0 left-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
216
<div className="absolute top-0 right-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
217
<div className="absolute bottom-0 left-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
218
<div className="absolute bottom-0 right-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
219
<div className="absolute border-x inset-block-0 inset-inline-[35px]" />
220
<div className="absolute border-y inset-inline-0 inset-block-[35px]" />
221
222
<Svg />
223
</div>
224
))}
225
</div>
226
}
227
/>
228
229
<BrandSection
230
title="Our colors"
231
preview={
232
<div className="grid grid-cols-12 gap-gutter">
233
<div className="col-span-12 grid grid-cols-2 gap-gutter">
234
{colors.slice(0, 2).map(({ hex, pantone, cmyk }) => (
235
<div key={hex} className="flex flex-col gap-2 text-left">
236
<div
237
style={{ backgroundColor: hex }}
238
className="h-28 rounded"
239
>
240
<div className="p-4 pt-14 text-white">
241
<div className="font-black">{hex}</div>
242
<div className="c2">
243
Pantone {pantone} &bull; CMYK {cmyk}
244
</div>
245
</div>
246
</div>
247
</div>
248
))}
249
</div>
250
<div className="col-span-12 grid grid-cols-3 gap-gutter lg:col-span-10 lg:col-start-2">
251
{colors.slice(2).map(({ hex, pantone, cmyk }) => (
252
<div key={hex} className="flex flex-col gap-2 text-left">
253
<div
254
style={{ backgroundColor: hex }}
255
className="h-28 rounded"
256
>
257
<div className="p-4 pt-14 text-white">
258
<div className="font-black">{hex}</div>
259
<div className="c2">
260
Pantone {pantone} &bull; CMYK {cmyk}
261
</div>
262
</div>
263
</div>
264
</div>
265
))}
266
</div>
267
</div>
268
}
269
/>
270
<BrandSection
271
title="Posters and flyers"
272
copy="Organising an event? We've got you covered."
273
preview={(
274
<div className="mb-16 flex gap-gutter">
275
<div className="flex max-w-full items-start">
276
<div className="relative w-[50%] shrink-0">
277
<Image
278
src={require("../public/promotional/poster_a4_en.jpg")}
279
alt=""
280
className="rounded-md"
281
/>
282
</div>
283
284
<div className="px-4 text-start">
285
<p className="mb-4"><strong className="font-black">Printing instructions:</strong></p>
286
287
<ul className="list-disc pl-3 mb-8">
288
<li>A4 paper</li>
289
<li>CMYK color space</li>
290
<li>3mm bleed</li>
291
</ul>
292
293
<p className="mb-4"><strong className="font-black">Download:</strong></p>
294
295
<ul className="list-disc pl-3">
296
<li><a className="text-blurple-600 hover:underline" href="/promotional/poster_a4_en.pdf">English (PDF)</a></li>
297
<li><a className="text-blurple-600 hover:underline" href="/promotional/poster_a4_de.pdf">Deutsch (PDF)</a></li>
298
<li><a className="text-blurple-600 hover:underline" href="/promotional/poster_a4_es.pdf">Español (PDF)</a></li>
299
<li><a className="text-blurple-600 hover:underline" href="/promotional/poster_a4_it.pdf">Italiano (PDF)</a></li>
300
</ul>
301
</div>
302
</div>
303
</div>
304
)}
305
/>
306
307
<BrandSection
308
title="Product screenshots"
309
copy="Need some screenshots? Here is a selection."
310
preview={
311
<div className="mb-16 grid grid-cols-5 gap-gutter">
312
{[
313
{
314
src: screenshotComposeLight,
315
title: "Compose, light mode, Android",
316
},
317
{
318
src: screenshotHomeLight,
319
title: "Home, light mode, Android",
320
},
321
{
322
src: screenshotProfileLight,
323
title: "Profile, light mode, Android",
324
},
325
{
326
src: screenshotServerRulesLight,
327
title: "Server rules, light mode, Android",
328
},
329
{
330
src: screenshotThreadLight,
331
title: "Thread, light mode, Android",
332
},
333
].map((screenshot) => (
334
<a
335
key={screenshot.title}
336
href={screenshot.src.src}
337
title={screenshot.title}
338
className="block col-span-1 overflow-hidden rounded border border-gray-4 ring-blurple-500 hocus:ring"
339
>
340
<Image src={screenshot.src} alt="" />
341
</a>
342
))}
343
</div>
344
}
345
/>
346
</div>
347
348
<Head>
349
<title>Brand Toolkit - Mastodon</title>
350
<meta property="og:title" content="Brand Toolkit for Mastodon" />
351
<meta
352
property="og:description"
353
content="Learn our branding guidelines, download our logos and icons, or use our brand colors for your projects."
354
/>
355
<meta
356
property="description"
357
content="Learn our branding guidelines, download our logos and icons, or use our brand colors for your projects."
358
/>
359
</Head>
360
</div>
361
</Layout>
362
)
363
export const getStaticProps = withDefaultStaticProps()
364
export default Branding
365
366