Landingsside som Svelte-komponent, fjern iframe (X-Frame-Options blokkerte)
LandingPage.svelte med all CSS og HTML innbakt. Ingen iframe, ingen ekstern fil-avhengighet. Fungerer i alle nettlesere. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
daf9660353
commit
8d914ed38f
2 changed files with 94 additions and 4 deletions
92
frontend/src/lib/components/LandingPage.svelte
Normal file
92
frontend/src/lib/components/LandingPage.svelte
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
<div class="landing">
|
||||||
|
<div class="container">
|
||||||
|
<header>
|
||||||
|
<div class="logo">synops<span>.</span></div>
|
||||||
|
<a href="/auth/signin" class="login-btn">Logg inn</a>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<h1>Stappfull av <em>features</em><br>(hvorav et fåtall virker som forutsatt)</h1>
|
||||||
|
<p class="tagline">En useriøs plattform for kommunikasjon, redaksjonelt arbeid, podcastproduksjon og egentlig alt du vil. Bygget med uvitenhet, overmot og en urimelig mengde AI-assistanse.</p>
|
||||||
|
<a href="/auth/signin" class="hero-cta">Kom i gang →</a>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<section class="features">
|
||||||
|
<div class="feature"><h3>Alt er noder</h3><p>Meldinger, oppgaver, lydfiler, dokumenter, mennesker — alt er samme ting med ulike relasjoner. Elegansen i dette vil slå deg en dag. Eller forvirre deg. Sannsynligvis begge.</p></div>
|
||||||
|
<div class="feature"><h3>Podcast-studio</h3><p>Spill inn med kolleger via nettleseren. Lydmixer, sound pads, stemmeeffekter og en AI som dytter fakta på deg mens du snakker. Om den finner noen.</p></div>
|
||||||
|
<div class="feature"><h3>Publiseringsplattform</h3><p>Skriv en chatmelding. Se den vokse til en artikkel. Publiser den på nettet med et tema som ser ut som du brukte måneder på det. Du brukte sekunder.</p></div>
|
||||||
|
<div class="feature"><h3>Spatial arbeidsflate</h3><p>Dra verktøy rundt på en uendelig flate. Chat ved siden av kanban ved siden av kalender ved siden av lydstudio. Det er som et skrivebord, bare at du aldri finner noe.</p></div>
|
||||||
|
<div class="feature"><h3>@bot overalt</h3><p>Skriv @bot i en hvilken som helst samtale. En AI svarer, diskuterer og fanger opp oppgaver i bakgrunnen. Hvilken AI? Den som tilfeldigvis er oppe akkurat nå.</p></div>
|
||||||
|
<div class="feature"><h3>Kunnskapsgraf</h3><p>Alt du skriver, sier og lenker bygger en levende graf av kunnskap. Synops husker sammenhenger du selv har glemt. Eller fabrikkerer nye. Vanskelig å si.</p></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<section class="faq">
|
||||||
|
<div class="faq-item"><h3>Er Synops sikkert?</h3><p>Hahaha. Overhodet ikke. Vi kjører på én server, med én utvikler, og en AI som committer kode uten tilsyn. Men dataene dine er i hvert fall kryptert i transit. Og vi mener det godt.</p></div>
|
||||||
|
<div class="faq-item"><h3>Kan jeg stole på at ting fungerer?</h3><p>Du kan stole på at vi prøver. Og at PostgreSQL er mer pålitelig enn resten av stacken. Sannsynligheten for at akkurat den funksjonen du trenger virker akkurat nå er statistisk sett overraskende høy.</p></div>
|
||||||
|
<div class="faq-item"><h3>Hvem er dette for?</h3><p>Folk som lager podcast, skriver tekster, eller driver redaksjonelt arbeid — og som har en uforklarlig toleranse for betaversjoner. Tålmodige optimister. Eventyrlystne journalister. Eller folk som bare vil pludre med noen kompiser og kanskje ha en videosamtale.</p></div>
|
||||||
|
<div class="faq-item"><h3>Koster det noe?</h3><p>Nei.. altså, aah. Hvis du har for mye penger så skal vi finne en måte å ta imot? Det koster utvikleren søvn og penger, men deg koster det ingenting. Foreløpig. Muligens for alltid. Vi har ikke kommet så langt i forretningsplanen.</p></div>
|
||||||
|
<div class="faq-item"><h3>Er det open source?</h3><p>Koden bor på en Forgejo-instans som er omtrent like tilgjengelig som resten av plattformen. Vi har intensjoner om åpenhet. Intensjoner er det vi er best på.</p></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<section class="reviews">
|
||||||
|
<div class="review"><div class="stars">★★☆☆☆</div><blockquote>«Jeg trodde virkelig dette hadde potensiale!»</blockquote><div class="author">— Anonym betatester</div></div>
|
||||||
|
<div class="review"><div class="stars">★★★☆☆</div><blockquote>«Ideen var ok. Gjennomføringen... original.»</blockquote><div class="author">— En som prøvde</div></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<section class="expect">
|
||||||
|
<h2>Hva kan du forvente?</h2>
|
||||||
|
<p>Som bruker av Synops kan du forvente en dønn ustabil plattform som er i stadig endring, men som du likevel tenker at det er en grunn til å være på. Nye features dukker opp uten forvarsel. Gamle features forsvinner uten forvarsel. Og en og annen gang fungerer alt samtidig — og da er det ganske magisk.</p>
|
||||||
|
<div class="cta-row"><a href="/auth/signin" class="hero-cta">Jeg er overbevist →</a></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer><p>synops.no — et hobbyprosjekt med ambisjoner over evne</p></footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Literata:ital,wght@0,400;0,700;1,400&display=swap');
|
||||||
|
.landing { background: #0a0a0b; color: #e8e8ec; font-family: 'Inter', -apple-system, sans-serif; line-height: 1.6; min-height: 100vh; }
|
||||||
|
.landing::before { content: ''; position: fixed; inset: 0; background-image: linear-gradient(rgba(99,102,241,0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(99,102,241,0.03) 1px, transparent 1px); background-size: 60px 60px; pointer-events: none; z-index: 0; }
|
||||||
|
.container { position: relative; z-index: 1; max-width: 800px; margin: 0 auto; padding: 0 24px; }
|
||||||
|
header { display: flex; justify-content: space-between; align-items: center; padding: 32px 0; }
|
||||||
|
.logo { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.02em; }
|
||||||
|
.logo span { color: #6366f1; }
|
||||||
|
.login-btn { padding: 10px 24px; background: #6366f1; color: white; border: none; border-radius: 8px; font-size: 0.9rem; font-weight: 500; text-decoration: none; transition: all 0.2s; }
|
||||||
|
.login-btn:hover { filter: brightness(1.15); transform: translateY(-1px); }
|
||||||
|
.hero { padding: 80px 0 60px; text-align: center; }
|
||||||
|
.hero h1 { font-size: clamp(2.5rem, 6vw, 4rem); font-weight: 700; letter-spacing: -0.03em; line-height: 1.1; margin-bottom: 24px; }
|
||||||
|
.hero h1 em { font-style: normal; background: linear-gradient(135deg, #6366f1, #a78bfa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
|
||||||
|
.tagline { font-family: 'Literata', Georgia, serif; font-style: italic; font-size: 1.15rem; color: #8a8a96; max-width: 560px; margin: 0 auto 48px; }
|
||||||
|
.hero-cta { display: inline-flex; padding: 14px 32px; background: #6366f1; color: white; border-radius: 10px; font-size: 1rem; font-weight: 600; text-decoration: none; box-shadow: 0 0 40px rgba(99,102,241,0.15); transition: all 0.2s; }
|
||||||
|
.hero-cta:hover { filter: brightness(1.15); transform: translateY(-2px); }
|
||||||
|
.divider { width: 48px; height: 1px; background: #2a2a2e; margin: 60px auto; }
|
||||||
|
.features { display: grid; gap: 20px; padding-bottom: 40px; }
|
||||||
|
.feature { background: #141416; border: 1px solid #2a2a2e; border-radius: 12px; padding: 28px 32px; transition: border-color 0.2s; }
|
||||||
|
.feature:hover { border-color: rgba(99,102,241,0.3); }
|
||||||
|
.feature h3 { font-size: 1rem; font-weight: 600; margin-bottom: 8px; }
|
||||||
|
.feature p { font-family: 'Literata', Georgia, serif; font-style: italic; color: #8a8a96; font-size: 0.95rem; line-height: 1.7; }
|
||||||
|
.faq { padding-bottom: 40px; }
|
||||||
|
.faq-item { border-bottom: 1px solid #2a2a2e; padding: 28px 0; }
|
||||||
|
.faq-item:first-child { border-top: 1px solid #2a2a2e; }
|
||||||
|
.faq-item h3 { font-size: 1rem; font-weight: 600; margin-bottom: 8px; }
|
||||||
|
.faq-item p { font-family: 'Literata', Georgia, serif; font-style: italic; color: #8a8a96; font-size: 0.95rem; line-height: 1.7; }
|
||||||
|
.reviews { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; padding-bottom: 40px; }
|
||||||
|
.review { background: #141416; border: 1px solid #2a2a2e; border-radius: 12px; padding: 24px; }
|
||||||
|
.review .stars { color: #6366f1; font-size: 0.85rem; margin-bottom: 10px; }
|
||||||
|
.review blockquote { font-family: 'Literata', Georgia, serif; font-style: italic; color: #8a8a96; font-size: 0.9rem; line-height: 1.6; }
|
||||||
|
.review .author { margin-top: 12px; font-size: 0.8rem; color: #8a8a96; opacity: 0.6; }
|
||||||
|
.expect { background: #141416; border: 1px solid #2a2a2e; border-radius: 16px; padding: 40px; margin-bottom: 60px; text-align: center; }
|
||||||
|
.expect h2 { font-size: 1.5rem; font-weight: 700; margin-bottom: 16px; }
|
||||||
|
.expect p { font-family: 'Literata', Georgia, serif; font-style: italic; color: #8a8a96; font-size: 1.05rem; line-height: 1.8; max-width: 580px; margin: 0 auto; }
|
||||||
|
.expect .cta-row { margin-top: 32px; }
|
||||||
|
footer { text-align: center; padding: 40px 0; border-top: 1px solid #2a2a2e; color: #8a8a96; font-size: 0.85rem; }
|
||||||
|
@media (max-width: 600px) { .hero { padding: 48px 0 40px; } .feature { padding: 20px 24px; } .expect { padding: 28px 24px; } .reviews { grid-template-columns: 1fr; } header { padding: 20px 0; } }
|
||||||
|
</style>
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
import NewChatDialog from '$lib/components/NewChatDialog.svelte';
|
import NewChatDialog from '$lib/components/NewChatDialog.svelte';
|
||||||
import AudioPlayer from '$lib/components/AudioPlayer.svelte';
|
import AudioPlayer from '$lib/components/AudioPlayer.svelte';
|
||||||
import { createNode, createEdge, createCommunication, casUrl } from '$lib/api';
|
import { createNode, createEdge, createCommunication, casUrl } from '$lib/api';
|
||||||
|
import LandingPage from '$lib/components/LandingPage.svelte';
|
||||||
|
|
||||||
const session = $derived($page.data.session as Record<string, unknown> | undefined);
|
const session = $derived($page.data.session as Record<string, unknown> | undefined);
|
||||||
const nodeId = $derived(session?.nodeId as string | undefined);
|
const nodeId = $derived(session?.nodeId as string | undefined);
|
||||||
|
|
@ -294,10 +295,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !$page.data.session?.user}
|
{#if !$page.data.session?.user}
|
||||||
<!-- Landingsside for uautentiserte — servert fra statisk fil via iframe -->
|
<LandingPage />
|
||||||
<div style="position: fixed; inset: 0; margin: 0; overflow: hidden;">
|
|
||||||
<iframe src="/landing" title="Synops" style="width: 100%; height: 100%; border: none;"></iframe>
|
|
||||||
</div>
|
|
||||||
{:else}
|
{:else}
|
||||||
<div class="min-h-screen bg-gray-50">
|
<div class="min-h-screen bg-gray-50">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue