Repository navigation
Expand file tree
/
Copy pathsite.ts
More file actions
226 lines (211 loc) · 8.72 KB
/
Copy pathsite.ts
File metadata and controls
226 lines (211 loc) · 8.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Single source of truth for brand, navigation and social links.
// Anything here can be overridden at runtime by a matching `settings` key.
import type { Settings } from "./types";
export const BRAND = {
name: "Developer MultiGroup",
short: "MultiGroup",
tagline: "Where Developers Become Together",
domain: "devmultigroup.com",
url: "https://devmultigroup.com",
email: "support@devmultigroup.com",
description:
"Developer MultiGroup; iOS, web, yapay zekâ ve daha fazlasında geliştiricilerin birlikte büyüdüğü gönüllü bir Türk yazılım topluluğu. Buluşmalar, konferanslar ve akademisiyle ücretsiz bootcamp'ler.",
} as const;
/** The one canonical, indexable apex host. Analytics + the noindex guard key off
* this. Single source of truth for every host comparison (middleware, layout,
* server capture). */
export const CANONICAL_HOST = BRAND.domain;
/** True when a request host IS the canonical apex, tolerating a trailing FQDN dot
* ("devmultigroup.com.") and case. URL.host already lowercases + strips :443/:80,
* so only the trailing dot needs normalizing. */
export function isApexHost(host: string | null | undefined): boolean {
return !!host && host.replace(/\.$/, "").toLowerCase() === CANONICAL_HOST;
}
/**
* `/gallery` ships built and reachable, but it has no photos yet. Until the
* first albums are uploaded it is kept OFF every discovery surface — header
* nav, footer, sitemap and llms.txt — so search engines and answer engines
* never meet an empty page (the page also self-`noindex`es while empty).
*
* The route itself stays live, so a direct link works and the admin can check
* the result. Flip this to `true` — one line, nothing else to edit — once the
* photos are in.
*/
export const GALLERY_PUBLIC = false;
export type NavChild = { label: string; href: string; soon?: boolean };
export type NavItem = { label: string; href: string; children?: NavChild[] };
export const NAV: NavItem[] = [
{ label: "Etkinlikler", href: "/events" },
{ label: "Akademi", href: "/academy" },
{
label: "İçerik",
href: "/blog",
children: [
{ label: "Blog", href: "/blog" },
{ label: "Podcast'ler", href: "/podcasts" },
{ label: "Kayıtlar", href: "/recordings" },
...(GALLERY_PUBLIC ? [{ label: "Galeri", href: "/gallery" }] : []),
{ label: "Kaynakça", href: "/kaynakca" },
],
},
{ label: "Mağaza", href: "/store" },
{ label: "Ekip", href: "/team" },
{
label: "Ekosistem",
href: "/communities",
children: [
{ label: "Topluluklar", href: "/communities" },
{ label: "İş Birlikleri", href: "/partnerships" },
{ label: "Şirketler", href: "/companies" },
{ label: "Konuşmacılar", href: "/speakers" },
],
},
];
export const COMPANIES: { name: string; logo: string }[] = [
{ name: "Google", logo: "/media/companies/google.png" },
{ name: "Trendyol", logo: "/media/companies/trendyol.png" },
{ name: "Hepsiburada", logo: "/media/companies/hepsiburada.png" },
{ name: "Akbank", logo: "/media/companies/akbank.png" },
{ name: "Teknasyon", logo: "/media/companies/teknasyon.png" },
{ name: "Softtech", logo: "/media/companies/softtech.png" },
{ name: "Wite", logo: "/media/companies/wite.png" },
{ name: "Lodos.io", logo: "/media/companies/lodos.png" },
];
export const FOOTER_NAV: { label: string; href: string }[] = [
{ label: "Ana Sayfa", href: "/" },
{ label: "Etkinlikler", href: "/events" },
{ label: "Akademi", href: "/academy" },
{ label: "Kayıtlar", href: "/recordings" },
...(GALLERY_PUBLIC ? [{ label: "Galeri", href: "/gallery" }] : []),
{ label: "Blog", href: "/blog" },
{ label: "Kaynakça", href: "/kaynakca" },
{ label: "Ekip", href: "/team" },
{ label: "Mağaza", href: "/store" },
{ label: "Bağlantılar", href: "/links" },
{ label: "İletişim", href: "/contact" },
{ label: "Marka & Basın", href: "/brand" },
];
/** Gizlilik / KVKK footer links. */
export const LEGAL_NAV: { label: string; href: string }[] = [
{ label: "Aydınlatma Metni", href: "/privacy" },
{ label: "Çerez Politikası", href: "/privacy/cerez-politikasi" },
{ label: "Bülten Onayı", href: "/privacy/bulten-onay" },
];
// Community platform pages (event registration routes here).
export const GATHIN = {
multigroup:
"https://gathin.com/communities/multigroup-community-34813861558366504236",
multiacademy:
"https://gathin.com/communities/multiacademy-community-94761667282726876508",
} as const;
/** "Aramıza katıl" join form (membership application). */
export const JOIN_FORM = "https://forms.gle/oAvMuvVMNjcb4BDo8";
export const SOCIALS = {
multigroup: {
instagram: "https://www.instagram.com/devmultigroup/",
twitter: "https://twitter.com/devmultigroup",
linkedin: "https://www.linkedin.com/company/developermultigroup",
youtube: "https://www.youtube.com/@devmultigroup",
github: "https://github.com/multigroupco",
kommunity: "https://kommunity.com/devmultigroup",
},
multiacademy: {
instagram: "https://www.instagram.com/devmultiacademy/",
linkedin: "https://www.linkedin.com/company/multiacademy-dev/",
youtube: "https://www.youtube.com/@devmultigroup",
},
multistore: {
instagram: "https://www.instagram.com/devmultistore/",
},
multiculture: {
instagram: "https://www.instagram.com/devmulticulture/",
},
} as const;
/** Sub-brands under the MultiGroup umbrella, shown in the footer's
* "Powered By MultiGroup" column. MultiCulture is intentionally a separate
* lane — only an Instagram, no site link for now. */
export const SUBBRANDS: {
strong: string;
tail: string;
desc: string;
href?: string;
hrefLabel?: string;
/** Internal linktree page for this sub-brand, shown as a link icon next to
* the socials (a hub of everything, not a social account). */
linktree?: { href: string; label: string };
socials: { icon: string; href: string; label: string }[];
}[] = [
{
strong: "Multi",
tail: "Academy",
desc: "Öğrenme kolu. Ücretsiz bootcamp'ler ve uygulamalı programlar.",
href: "/academy",
hrefLabel: "Akademi",
linktree: { href: "/academy-links", label: "MultiAcademy bağlantıları" },
socials: [
{ icon: "instagram", href: SOCIALS.multiacademy.instagram, label: "MultiAcademy Instagram" },
{ icon: "linkedin", href: SOCIALS.multiacademy.linkedin, label: "MultiAcademy LinkedIn" },
{ icon: "youtube", href: SOCIALS.multiacademy.youtube, label: "MultiAcademy YouTube" },
],
},
{
strong: "Multi",
tail: "Store",
desc: "Ürün kolu. Topluluk merch'i, etkinlikte teslim ön sipariş drop'ları.",
href: "/store",
hrefLabel: "Mağaza",
socials: [{ icon: "instagram", href: SOCIALS.multistore.instagram, label: "MultiStore Instagram" }],
},
{
strong: "Multi",
tail: "Culture",
desc: "Topluluğun kültür ve yaşam kolu.",
socials: [{ icon: "instagram", href: SOCIALS.multiculture.instagram, label: "MultiCulture Instagram" }],
},
];
export interface SiteConfig {
title: string;
tagline: string;
description: string;
gaMeasurementId: string;
gscVerification: string;
/** PostHog project (public) API key — `phc_…`. Empty disables PostHog. */
posthogKey: string;
/** PostHog ingestion host (US cloud by default). */
posthogHost: string;
/** Sentry browser DSN (public). Empty disables client error monitoring. */
sentryDsn: string;
/** Master kill-switch: "0" turns off ALL analytics regardless of keys. */
analyticsEnabled: boolean;
bannerEnabled: boolean;
members: string;
cities: string;
events: string;
recordings: string;
companies: string;
speakers: string;
/** Cumulative reach across collaborations — shown on /partnerships. */
partnerReach: string;
}
/** Merge DB settings over sane defaults so the site renders before seeding. */
export function resolveSite(settings: Settings): SiteConfig {
return {
title: settings.site_title || BRAND.name,
tagline: settings.site_tagline || BRAND.tagline,
description: settings.site_description || BRAND.description,
gaMeasurementId: settings.ga_measurement_id || "",
gscVerification: settings.gsc_verification || "",
posthogKey: settings.posthog_key || "",
posthogHost: (settings.posthog_host || "https://eu.i.posthog.com").replace(/\/$/, ""),
sentryDsn: settings.sentry_dsn || "",
analyticsEnabled: (settings.analytics_enabled ?? "1") !== "0",
bannerEnabled: (settings.banner_enabled ?? "1") !== "0",
members: settings.stat_members || "15.000+",
cities: settings.stat_cities || "İstanbul",
events: settings.stat_events || "100+",
recordings: settings.stat_recordings || "17+",
companies: settings.stat_companies || "25+",
speakers: settings.stat_speakers || "200+",
partnerReach: settings.stat_partner_reach || "750+",
};
}