Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/components/CTASection.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import "../index.css";
import { useLanguage } from '../i18n/LanguageProvider';

function CTASection() {
const { strings } = useLanguage();

return (
<div className="relative isolate mt-32 px-6 py-32 sm:mt-56 sm:py-40 lg:px-8">
<svg
Expand Down Expand Up @@ -40,23 +43,23 @@ function CTASection() {
</div>
<div className="mx-auto max-w-2xl text-center">
<h2 className="text-balance text-4xl font-semibold tracking-tight text-white sm:text-5xl">
Try it out - if you like it, keep it
{strings.test_title}
</h2>
<p className="mx-auto mt-6 max-w-xl text-lg/8 text-gray-300">
It&#39;s open source and GPL licensed. Enjoy.
{strings.test_catchphrase}
</p>
<div className="mt-10 flex items-center justify-center gap-x-6">
<a
href="https://truspace.dev/login"
className="rounded-md bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:text-white shadow-sm hover:bg-indigo-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-400"
>
Login
{strings.login}
</a>
<a
href="https://truspace.dev/register"
className="text-sm/6 font-semibold text-white hover:text-white hover:underline"
>
Register<span aria-hidden="true">→</span>
{strings.register}<span aria-hidden="true">→</span>
</a>
</div>
</div>
Expand Down
44 changes: 19 additions & 25 deletions src/components/FeatureDetails.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { useLanguage } from '../i18n/LanguageProvider';

function FeatureDetails() {
const { strings } = useLanguage();

return (
<>
<div className="mt-32 sm:mt-56">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl sm:text-center">
<h2 className="text-base/7 font-semibold text-indigo-400">
Sovereign - decentralized - secure
{strings.feature_subtitle}
</h2>
<p className="mt-2 text-pretty text-4xl font-semibold tracking-tight text-white sm:text-balance sm:text-5xl">
Trusted Space - using a federated private network
{strings.feature_title}
</p>
<p className="mt-6 text-lg/8 text-gray-300">
Don't depend on anyone - keep control of your documents and keep
them in sync in your network
{strings.feature_catchphrase}
<br />
</p>
</div>
Expand Down Expand Up @@ -47,11 +50,10 @@ function FeatureDetails() {
clipRule="evenodd"
/>
</svg>
Sovereignty{" "}
{strings.feature1_title}{" "}
</dt>
<dd className="inline">
Take back control of your data with decentralized, tamper-proof
storage—your documents, your rules, no middlemen.
{strings.feature1_explanation}
</dd>
</div>
<div className="relative pl-9">
Expand All @@ -69,12 +71,10 @@ function FeatureDetails() {
clipRule="evenodd"
/>
</svg>
Collaboration{" "}
{strings.feature2_title}{" "}
</dt>
<dd className="inline">
Work smarter with a shared space that unites documents, chat,
and versioning—finally, real-time teamwork that doesn&#39;t
suck.
{strings.feature2_explanation}
</dd>
</div>
<div className="relative pl-9">
Expand All @@ -92,11 +92,10 @@ function FeatureDetails() {
clipRule="evenodd"
/>
</svg>
Perspective{" "}
{strings.feature3_title}{" "}
</dt>
<dd className="inline">
Go beyond chatbots: check AI-generated insights through
best-practice prompts that you don't have to enter yourself
{strings.feature3_explanation}
</dd>
</div>
<div className="relative pl-9">
Expand All @@ -114,11 +113,10 @@ function FeatureDetails() {
clipRule="evenodd"
/>
</svg>
Choice{" "}
{strings.feature4_title}{" "}
</dt>
<dd className="inline">
Pick the AI that aligns with your values—whether it&#39;s
OpenAI, LLAMA, or your own model, you&#39;re in charge.
{strings.feature4_explanation}
</dd>
</div>
<div className="relative pl-9">
Expand All @@ -136,13 +134,10 @@ function FeatureDetails() {
clipRule="evenodd"
/>
</svg>
Resilience{" "}
{strings.feature5_title}{" "}
</dt>
<dd className="inline">
Built on a private IPFS network for robust sync and
integrity—even during network splits, your collaboration
doesn&#39;t break. With content-based addressing, data is
tamper-proof.
{strings.feature5_explanation}
</dd>
</div>
<div className="relative pl-9">
Expand All @@ -161,11 +156,10 @@ function FeatureDetails() {
clipRule="evenodd"
/>
</svg>
Commons{" "}
{strings.feature6_title}{" "}
</dt>
<dd className="inline">
Open-source and non-commercial by design—TruSpace is a digital
public good meant to evolve with the community.
{strings.feature6_explanation}
</dd>
</div>
</dl>
Expand Down
35 changes: 16 additions & 19 deletions src/components/FeatureSection.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { useLanguage } from '../i18n/LanguageProvider';

function FeatureSection() {
const { strings } = useLanguage();

return (
<div className="mx-auto mt-32 max-w-7xl px-6 sm:mt-56 lg:px-8">
<div className="mx-auto max-w-2xl lg:text-center">
<h2 className="text-base/7 font-semibold text-indigo-400">
Simply work together
{strings.tech_subtitle}
</h2>
<p className="mt-2 text-pretty text-4xl font-semibold tracking-tight text-white sm:text-5xl lg:text-balance">
Decentralized data storage and local sovereign AI
{strings.tech_title}
</p>
<p className="mt-6 text-lg/8 text-gray-300">
All data is stored and processed locally using IPFS - it cannot be
manipulated
{strings.tech_catchphrase}
</p>
</div>
<div className="mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-none">
Expand All @@ -34,20 +37,18 @@ function FeatureSection() {
/>
</svg>
</div>
Sovereign
{strings.tech1_title}
</dt>
<dd className="mt-1 flex flex-auto flex-col text-base/7 text-gray-300">
<p className="flex-auto">
All the data on your server. With open code. Nothing to hide.
Full control of the data - and with content-based addressing no
chance for hackers.
{strings.tech1_explanation}
</p>
<p className="mt-6">
<a
href="https://github.com/openkfw/TruSpace"
className="text-sm/6 font-semibold text-indigo-400"
>
Learn more <span aria-hidden="true">→</span>
{strings.learn_more} <span aria-hidden="true">→</span>
</a>
</p>
</dd>
Expand All @@ -71,20 +72,18 @@ function FeatureSection() {
/>
</svg>
</div>
Decentralized
{strings.tech2_title}
</dt>
<dd className="mt-1 flex flex-auto flex-col text-base/7 text-gray-300">
<p className="flex-auto">
You can't agree who should host the data? You don't have to. The
IPFS cluster syncs everything across everyone who likes to join
the network. And no one else.
{strings.tech2_explanation}
</p>
<p className="mt-6">
<a
href="https://github.com/openkfw/TruSpace"
className="text-sm/6 font-semibold text-indigo-400"
>
Learn more <span aria-hidden="true">→</span>
{strings.learn_more} <span aria-hidden="true">→</span>
</a>
</p>
</dd>
Expand All @@ -108,20 +107,18 @@ function FeatureSection() {
/>
</svg>
</div>
AI-infused
{strings.tech3_title}
</dt>
<dd className="mt-1 flex flex-auto flex-col text-base/7 text-gray-300">
<p className="flex-auto">
Pre-analyse all documents for summaries, inconsistencies and
everything you like. Of course with locally hosted AI and the
engine that you choose.
{strings.tech3_explanation}
</p>
<p className="mt-6">
<a
href="https://github.com/openkfw/TruSpace"
className="text-sm/6 font-semibold text-indigo-400"
>
Learn more <span aria-hidden="true">→</span>
{strings.learn_more} <span aria-hidden="true">→</span>
</a>
</p>
</dd>
Expand Down
8 changes: 6 additions & 2 deletions src/components/Footer.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { useLanguage } from '../i18n/LanguageProvider';

function Footer() {
const { strings } = useLanguage();

return (
<footer className="relative z-10 mx-auto max-w-7xl px-6 lg:px-8">
<div className="border-t border-white/10 py-12 md:flex md:items-center md:justify-between">
<p className="text-center text-sm/6 text-gray-400 md:mt-0">
&copy; 2025 TruSpace,
<a href="https://github.com/openkfw/TruSpace"> Impressum here</a>
&copy; {strings.copyright}
<a href="https://github.com/openkfw/TruSpace">{strings.impressum}</a>
</p>
<div className="mt-8 md:mt-0 flex justify-center">
<a
Expand Down
67 changes: 65 additions & 2 deletions src/components/HeaderBar.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,81 @@
import React, { useState, useRef, useEffect } from 'react';
import { useLanguage } from '../i18n/LanguageProvider';

function HeaderBar() {
const { lang, setLang, strings, allLanguages } = useLanguage();
const [open, setOpen] = useState(false);
const containerRef = useRef(null);

// Close on outside click
useEffect(() => {
function onDoc(e) {
if (!containerRef.current) return;
if (!containerRef.current.contains(e.target)) setOpen(false);
}
document.addEventListener('mousedown', onDoc);
return () => document.removeEventListener('mousedown', onDoc);
}, []);

const switchLabel = lang; // ENG or ESP

return (
<div className="sticky top-0 z-50 w-full bg-gray-900 px-4 py-2 shadow-lg">
<div className="flex justify-end items-center gap-4">
{/* Language switcher */}
<div className="relative" ref={containerRef}>
<button
onClick={() => setOpen((s) => !s)}
aria-haspopup="menu"
aria-expanded={open}
className="inline-flex items-center gap-1 px-2 py-1 text-sm text-white hover:text-white hover:bg-gray-600 cursor-pointer"
title="Select language"
type="button"
>
<span className="font-semibold">{switchLabel}</span>
<span className="transform rotate-90 text-xs leading-none">›</span>
</button>

{open && (
<div
role="menu"
className="absolute right-0 mt-2 min-w-[120px] rounded bg-gray-800 shadow-md ring-1 ring-black ring-opacity-5 z-50"
style={{zIndex: 9999}}
>
<ul className="py-1">
{Object.keys(allLanguages).map((key) => (
<li key={key}>
<button
role="menuitem"
onClick={() => {
setLang(key);
setOpen(false);
}}
className={`cursor-pointer w-full text-left px-3 py-2 text-sm ${
key === lang ? 'bg-gray-700 font-semibold' : 'hover:bg-gray-700'
}`}
type="button"
>
<span className="mr-2 text-xs">{key}</span>
<span className="text-gray-200 text-sm">{allLanguages[key].name}</span>
</button>
</li>
))}
</ul>
</div>
)}
</div>

<a
href="https://truspace.dev/login"
className="rounded-md bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:text-white shadow-sm hover:bg-indigo-400 focus-visible:outline focus-visible:outline-offset-2 focus-visible:outline-indigo-400"
>
Login
{strings.login}
</a>
<a
href="https://truspace.dev/register"
className="text-sm/6 font-semibold text-white hover:text-white hover:underline"
>
Register
{strings.register}
</a>
<a
href="https://github.com/openkfw/TruSpace"
Expand Down
25 changes: 19 additions & 6 deletions src/components/Hero.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import "../index.css";
import { useLanguage } from '../i18n/LanguageProvider';
import { useEffect, useState } from "react";

function Hero() {
const { strings } = useLanguage();
const [latestVersion, setLatestVersion] = useState(null);

useEffect(() => {
fetch("https://api.github.com/repos/openkfw/TruSpace/releases/latest")
.then((res) => res.json())
.then((data) => setLatestVersion(data.tag_name))
.catch(() => setLatestVersion(null));
}, []);

return (
<div className="relative isolate overflow-hidden">
<div
Expand All @@ -15,12 +27,14 @@ function Hero() {
<div className="mt-24 sm:mt-32 lg:mt-16">
<div className="inline-flex space-x-6 items-center">
<span className="rounded-full bg-indigo-500/10 px-3 py-1 text-sm/6 font-semibold text-indigo-400 ring-1 ring-inset ring-indigo-500/20">
What&#39;s new
{strings.whatsnew}
</span>
<span className="inline-flex items-center space-x-2 text-sm/6 font-medium text-gray-300">
<span>
Just shipped{" "}
<a href="https://github.com/openkfw/TruSpace">v0.8</a>
{strings.shipped}{" "}
<a href="https://github.com/openkfw/TruSpace">
{latestVersion ? latestVersion : "…"}
</a>
</span>
<svg
className="size-5 text-gray-500"
Expand Down Expand Up @@ -57,11 +71,10 @@ function Hero() {
</div>
</div>
<h1 className="mt-10 text-pretty text-5xl font-semibold tracking-tight text-white sm:text-7xl">
AI-infused trusted document collaboration
{strings.main_title}
</h1>
<p className="mt-8 text-pretty text-lg font-medium text-gray-400 sm:text-xl/8">
Share documents with whoever you decide and no one else - keep
control over your data and the AI you&#39;re working with.
{strings.main_catchphrase}
</p>
</div>
<div className="mx-auto mt-16 flex max-w-2xl sm:mt-24 lg:ml-10 lg:mr-0 lg:mt-0 lg:max-w-none lg:flex-none xl:ml-32">
Expand Down
Loading