first test

This commit is contained in:
Tomas Dvorak
2026-02-08 14:14:55 +01:00
parent 18aa702174
commit d27cf14110
372 changed files with 98087 additions and 2583 deletions
+37
View File
@@ -0,0 +1,37 @@
<template>
<div id="app" :class="{ 'dark': isDark }">
<Navigation />
<router-view />
<Footer />
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import Navigation from './components/Navigation.vue'
import Footer from './components/Footer.vue'
import { useTheme } from './composables/useTheme'
const { isDark } = useTheme()
onMounted(() => {
// Check for system preference
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
})
</script>
<style>
#app {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.dark {
color-scheme: dark;
}
</style>
+22
View File
@@ -0,0 +1,22 @@
<template>
<div class="card-papra group hover:scale-105 transition-papra duration-300 border-2 border-transparent hover:border-primary/20">
<div class="flex items-center mb-6">
<div class="bg-gradient-to-br from-primary/10 to-primary/20 text-primary p-4 rounded-2xl group-hover:from-primary/20 group-hover:to-primary/30 transition-papra">
<i :class="icon" class="text-3xl"></i>
</div>
</div>
<h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-4 leading-tight">{{ title }}</h3>
<p class="text-lg text-gray-600 dark:text-gray-400 leading-relaxed text-pretty">{{ description }}</p>
</div>
</template>
<script setup lang="ts">
interface Props {
icon: string
title: string
description: string
}
defineProps<Props>()
</script>
+78
View File
@@ -0,0 +1,78 @@
<template>
<footer class="bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 mt-auto">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<!-- Logo and Description -->
<div class="col-span-1 md:col-span-2">
<div class="flex items-center mb-4">
<img
src="/trackeep-logo-bg.png"
alt="Trackeep"
class="h-8 w-auto mr-3"
@error="(e: Event) => { const target = e.target as HTMLImageElement; target.style.display='none'; logoError = true }"
/>
<span v-if="logoError" class="text-xl font-bold text-primary">Trackeep</span>
</div>
<p class="text-gray-600 dark:text-gray-400 max-w-md">
Your self-hosted productivity & knowledge hub. Track, save, and organize everything that matters to you - all in one place, under your control.
</p>
</div>
<!-- Product Links -->
<div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4">Product</h3>
<ul class="space-y-2">
<li><a href="#features" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">Features</a></li>
<li><a href="#how-it-works" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">How It Works</a></li>
<li><a href="https://demo.trackeep.org" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">Demo</a></li>
<li><a href="https://github.com/trackeep/trackeep/releases" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">Changelog</a></li>
</ul>
</div>
<!-- Resources Links -->
<div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4">Resources</h3>
<ul class="space-y-2">
<li><a href="https://docs.trackeep.org" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">Documentation</a></li>
<li><a href="https://github.com/trackeep/trackeep" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">GitHub</a></li>
<li><a href="https://discord.gg/trackeep" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">Discord</a></li>
<li><a href="mailto:[email protected]" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">Contact</a></li>
</ul>
</div>
</div>
<!-- Bottom Section -->
<div class="mt-8 pt-8 border-t border-gray-200 dark:border-gray-700">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="flex items-center space-x-6 mb-4 md:mb-0">
<a href="/privacy" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors text-sm">Privacy Policy</a>
<a href="/terms" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors text-sm">Terms of Service</a>
</div>
<div class="flex items-center space-x-4">
<a href="https://github.com/trackeep/trackeep" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
<i class="ph ph-github-logo text-xl"></i>
</a>
<a href="https://discord.gg/trackeep" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
<i class="ph ph-discord-logo text-xl"></i>
</a>
<a href="https://twitter.com/trackeep" target="_blank" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
<i class="ph ph-twitter-logo text-xl"></i>
</a>
</div>
</div>
<div class="mt-4 text-center text-gray-600 dark:text-gray-400 text-sm">
© {{ currentYear }} Trackeep. All rights reserved. Built with and open source.
</div>
</div>
</div>
</footer>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
const logoError = ref(false)
const currentYear = computed(() => new Date().getFullYear())
</script>
+93
View File
@@ -0,0 +1,93 @@
<template>
<nav class="sticky top-0 z-50 bg-white/95 dark:bg-gray-900/95 backdrop-blur-xl border-b border-gray-200/50 dark:border-gray-700/50 shadow-soft">
<div class="max-w-7xl mx-auto px-6 sm:px-8 lg:px-12">
<div class="flex justify-between items-center h-20">
<!-- Logo -->
<div class="flex items-center">
<div class="flex-shrink-0">
<img
src="/trackeep-logo-bg.png"
alt="Trackeep"
class="h-10 w-auto transition-papra hover:scale-105"
@error="(e: Event) => { const target = e.target as HTMLImageElement; target.style.display='none'; logoError = true }"
/>
<span v-if="logoError" class="text-3xl font-bold text-primary tracking-tight">Trackeep</span>
</div>
</div>
<!-- Desktop Navigation -->
<div class="hidden lg:block">
<div class="flex items-center space-x-12">
<a href="#features" @click="(e) => handleNavClick(e, 'features')" class="nav-item-papra text-lg">Features</a>
<a href="#how-it-works" @click="(e) => handleNavClick(e, 'how-it-works')" class="nav-item-papra text-lg">How It Works</a>
<a href="#tech-stack" @click="(e) => handleNavClick(e, 'tech-stack')" class="nav-item-papra text-lg">Tech Stack</a>
<a href="https://docs.trackeep.org" target="_blank" class="nav-item-papra text-lg">Docs</a>
<a href="https://github.com/trackeep/trackeep" target="_blank" class="nav-item-papra text-lg flex items-center gap-2">
<i class="ph ph-github-logo text-xl"></i>
GitHub
</a>
</div>
</div>
<!-- Theme Toggle & Mobile Menu Button -->
<div class="flex items-center space-x-4">
<button
@click="toggleTheme"
class="p-3 rounded-xl hover:bg-gray-100 dark:hover:bg-gray-800 transition-papra group"
:aria-label="isDark ? 'Switch to light mode' : 'Switch to dark mode'"
>
<i :class="isDark ? 'ph ph-sun' : 'ph ph-moon'" class="text-xl text-gray-600 dark:text-gray-400 group-hover:text-primary transition-colors"></i>
</button>
<!-- Mobile menu button -->
<button
@click="toggleMobileMenu"
class="lg:hidden p-3 rounded-xl hover:bg-gray-100 dark:hover:bg-gray-800 transition-papra"
:aria-label="isMobileMenuOpen ? 'Close menu' : 'Open menu'"
>
<i :class="isMobileMenuOpen ? 'ph ph-x' : 'ph ph-list'" class="text-xl text-gray-600 dark:text-gray-400"></i>
</button>
</div>
</div>
<!-- Mobile Navigation -->
<div v-if="isMobileMenuOpen" class="lg:hidden border-t border-gray-200 dark:border-gray-700 mt-4 pt-4">
<div class="space-y-3">
<a href="#features" @click="(e) => handleNavClick(e, 'features')" class="block px-4 py-3 text-lg nav-item-papra rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800">Features</a>
<a href="#how-it-works" @click="(e) => handleNavClick(e, 'how-it-works')" class="block px-4 py-3 text-lg nav-item-papra rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800">How It Works</a>
<a href="#tech-stack" @click="(e) => handleNavClick(e, 'tech-stack')" class="block px-4 py-3 text-lg nav-item-papra rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800">Tech Stack</a>
<a href="https://docs.trackeep.org" @click="closeMobileMenu" target="_blank" class="block px-4 py-3 text-lg nav-item-papra rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800">Docs</a>
<a href="https://github.com/trackeep/trackeep" @click="closeMobileMenu" target="_blank" class="block px-4 py-3 text-lg nav-item-papra rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 flex items-center gap-2">
<i class="ph ph-github-logo text-xl"></i>
GitHub
</a>
</div>
</div>
</div>
</nav>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useTheme } from '../composables/useTheme'
import { useSmoothScroll } from '../composables/useSmoothScroll'
const { isDark, toggleTheme } = useTheme()
const { scrollToSection } = useSmoothScroll()
const isMobileMenuOpen = ref(false)
const logoError = ref(false)
const toggleMobileMenu = () => {
isMobileMenuOpen.value = !isMobileMenuOpen.value
}
const closeMobileMenu = () => {
isMobileMenuOpen.value = false
}
const handleNavClick = (event: Event, sectionId: string) => {
event.preventDefault()
scrollToSection(sectionId)
closeMobileMenu()
}
</script>
+134
View File
@@ -0,0 +1,134 @@
<template>
<div class="card-papra max-w-4xl mx-auto lg:mx-0 border-2 border-primary/20">
<div class="mb-8">
<h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-3 tracking-tight">Quick Install</h3>
<p class="text-lg text-gray-600 dark:text-gray-400 leading-relaxed">Get Trackeep running in seconds with one command</p>
</div>
<!-- Command Box -->
<div class="relative bg-gray-900 dark:bg-black border border-gray-700 dark:border-gray-600 rounded-2xl p-6 mb-8 shadow-strong">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center space-x-2">
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
</div>
<span class="text-xs text-gray-400 font-mono">terminal</span>
</div>
<code class="text-lg font-mono text-green-400 break-leading-relaxed block">
$ curl -sSL https://trackeep.org/install.sh | sh
</code>
<!-- Copy Button -->
<button
@click="copyCommand"
class="absolute top-6 right-6 p-3 bg-gray-800 hover:bg-gray-700 rounded-xl transition-papra group"
:aria-label="copied ? 'Copied!' : 'Copy command'"
>
<i :class="copied ? 'ph ph-check text-green-400' : 'ph ph-copy text-gray-400 group-hover:text-white'" class="text-xl transition-colors"></i>
</button>
</div>
<!-- Success Message -->
<div v-if="copied" class="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-2xl p-4 mb-8 shadow-soft">
<p class="text-green-800 dark:text-green-200 font-medium flex items-center">
<i class="ph ph-check-circle mr-2 text-xl"></i>
Command copied to clipboard! Ready to install Trackeep.
</p>
</div>
<!-- Social Proof Buttons -->
<div class="flex flex-wrap gap-4 mb-8">
<a
href="https://github.com/trackeep/trackeep"
target="_blank"
class="flex items-center gap-3 px-6 py-3 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl hover:bg-gray-100 dark:hover:bg-gray-700 transition-papra group"
>
<i class="ph ph-github-logo text-xl text-gray-600 dark:text-gray-400 group-hover:text-primary transition-colors"></i>
<span class="font-medium text-gray-700 dark:text-gray-300">View Source</span>
</a>
<a
href="https://discord.gg/trackeep"
target="_blank"
class="flex items-center gap-3 px-6 py-3 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl hover:bg-gray-100 dark:hover:bg-gray-700 transition-papra group"
>
<i class="ph ph-discord-logo text-xl text-gray-600 dark:text-gray-400 group-hover:text-primary transition-colors"></i>
<span class="font-medium text-gray-700 dark:text-gray-300">Join Discord</span>
</a>
<a
href="https://docs.trackeep.org"
target="_blank"
class="flex items-center gap-3 px-6 py-3 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl hover:bg-gray-100 dark:hover:bg-gray-700 transition-papra group"
>
<i class="ph ph-book text-xl text-gray-600 dark:text-gray-400 group-hover:text-primary transition-colors"></i>
<span class="font-medium text-gray-700 dark:text-gray-300">Documentation</span>
</a>
</div>
<!-- Installation Info -->
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-2xl p-6">
<div class="flex items-start gap-3">
<div class="bg-blue-100 dark:bg-blue-900/50 text-blue-600 dark:text-blue-400 p-2 rounded-lg">
<i class="ph ph-info text-xl"></i>
</div>
<div class="text-sm text-gray-700 dark:text-gray-300">
<p class="font-semibold mb-3 text-gray-900 dark:text-gray-100">The install script will:</p>
<ul class="space-y-2 ml-4">
<li class="flex items-start gap-2">
<i class="ph ph-check-circle text-green-500 mt-0.5 flex-shrink-0"></i>
<span>Check system requirements (Docker, Docker Compose)</span>
</li>
<li class="flex items-start gap-2">
<i class="ph ph-check-circle text-green-500 mt-0.5 flex-shrink-0"></i>
<span>Download the latest Trackeep release</span>
</li>
<li class="flex items-start gap-2">
<i class="ph ph-check-circle text-green-500 mt-0.5 flex-shrink-0"></i>
<span>Set up environment variables and database</span>
</li>
<li class="flex items-start gap-2">
<i class="ph ph-check-circle text-green-500 mt-0.5 flex-shrink-0"></i>
<span>Start all services and provide access URLs</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const copied = ref(false)
const copyCommand = async () => {
const command = 'curl -sSL https://trackeep.org/install.sh | sh'
try {
await navigator.clipboard.writeText(command)
copied.value = true
// Reset after 3 seconds
setTimeout(() => {
copied.value = false
}, 3000)
} catch (err) {
// Fallback for older browsers
const textArea = document.createElement('textarea')
textArea.value = command
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
copied.value = true
setTimeout(() => {
copied.value = false
}, 3000)
}
}
</script>
@@ -0,0 +1,15 @@
export function useSmoothScroll() {
const scrollToSection = (elementId: string) => {
const element = document.getElementById(elementId)
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'start'
})
}
}
return {
scrollToSection
}
}
+38
View File
@@ -0,0 +1,38 @@
import { ref, watch } from 'vue'
export function useTheme() {
const isDark = ref(false)
const toggleTheme = () => {
isDark.value = !isDark.value
updateTheme()
}
const updateTheme = () => {
if (isDark.value) {
document.documentElement.classList.add('dark')
localStorage.theme = 'dark'
} else {
document.documentElement.classList.remove('dark')
localStorage.theme = 'light'
}
}
const initTheme = () => {
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
isDark.value = true
document.documentElement.classList.add('dark')
} else {
isDark.value = false
document.documentElement.classList.remove('dark')
}
}
watch(isDark, updateTheme)
return {
isDark,
toggleTheme,
initTheme
}
}
+9
View File
@@ -0,0 +1,9 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import 'uno.css'
const app = createApp(App)
app.use(router)
app.mount('#app')
+14
View File
@@ -0,0 +1,14 @@
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'home',
component: () => import('./views/Home.vue')
}
]
})
export default router
+448
View File
@@ -0,0 +1,448 @@
<template>
<div class="min-h-screen">
<!-- Hero Section -->
<section class="relative py-24 lg:py-32 bg-gradient-to-br from-white via-gray-50 to-white dark:from-gray-900 dark:via-gray-800 dark:to-gray-900">
<div class="max-w-7xl mx-auto px-6 sm:px-8 lg:px-12">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-16 lg:gap-20 items-center">
<!-- Left Content -->
<div class="text-center lg:text-left space-y-8">
<div class="space-y-6">
<h1 class="text-5xl lg:text-7xl font-bold text-gray-900 dark:text-gray-100 leading-tight tracking-tight">
Your Self-Hosted
<span class="text-primary">Productivity</span>
<br class="hidden lg:block" />
& <span class="text-primary">Knowledge</span> Hub
</h1>
<p class="text-xl lg:text-2xl text-gray-600 dark:text-gray-400 leading-relaxed text-pretty max-w-2xl">
Track, save, and organize everything that matters to you all in one place, under your control.
No subscriptions, no data mining, just pure productivity.
</p>
</div>
<!-- Quick Install Component -->
<QuickInstall class="scale-95 lg:scale-100" />
<!-- Feature Highlights -->
<div class="grid grid-cols-1 sm:grid-cols-3 gap-6 pt-8">
<div class="text-center lg:text-left group">
<div class="flex items-center justify-center lg:justify-start mb-3">
<div class="bg-primary/10 text-primary p-3 rounded-xl group-hover:bg-primary/20 transition-papra">
<i class="ph ph-lock-simple text-2xl"></i>
</div>
<span class="font-semibold text-gray-900 dark:text-gray-100 ml-3">Privacy First</span>
</div>
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">Your data stays yours</p>
</div>
<div class="text-center lg:text-left group">
<div class="flex items-center justify-center lg:justify-start mb-3">
<div class="bg-primary/10 text-primary p-3 rounded-xl group-hover:bg-primary/20 transition-papra">
<i class="ph ph-code text-2xl"></i>
</div>
<span class="font-semibold text-gray-900 dark:text-gray-100 ml-3">Open Source</span>
</div>
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">Transparent & customizable</p>
</div>
<div class="text-center lg:text-left group">
<div class="flex items-center justify-center lg:justify-start mb-3">
<div class="bg-primary/10 text-primary p-3 rounded-xl group-hover:bg-primary/20 transition-papra">
<i class="ph ph-devices text-2xl"></i>
</div>
<span class="font-semibold text-gray-900 dark:text-gray-100 ml-3">All-in-One</span>
</div>
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">Replace multiple apps</p>
</div>
</div>
<!-- CTA Buttons -->
<div class="flex flex-col sm:flex-row gap-4 justify-center lg:justify-start pt-8">
<a href="#features" @click="(e) => handleCTAClick(e, 'features')" class="btn-primary text-center">
Explore Features
</a>
<a href="https://demo.trackeep.org" target="_blank" class="btn-outline text-center">
View Demo
</a>
</div>
</div>
<!-- Right Content - Hero Image -->
<div class="relative">
<div class="relative rounded-3xl overflow-hidden shadow-strong">
<img
src="/hero-dashboard.png"
alt="Trackeep Dashboard"
class="w-full h-auto transform hover:scale-105 transition-papra duration-700"
@error="(e: Event) => { const target = e.target as HTMLImageElement; target.style.display='none'; heroImageError = true }"
/>
<!-- Placeholder if image fails to load -->
<div v-if="heroImageError" class="bg-gradient-to-br from-gray-100 to-gray-200 dark:from-gray-800 dark:to-gray-700 border border-gray-200 dark:border-gray-600 rounded-3xl p-16 min-h-[500px] flex items-center justify-center">
<div class="text-center">
<i class="ph ph-monitor text-8xl text-primary mb-6"></i>
<p class="text-xl text-gray-600 dark:text-gray-400 font-medium">Dashboard Preview</p>
</div>
</div>
</div>
<!-- Floating badges -->
<div class="absolute -top-6 -right-6 bg-primary text-white px-6 py-3 rounded-2xl font-bold shadow-strong transform rotate-3">
v1.0.0
</div>
<div class="absolute -bottom-6 -left-6 bg-white dark:bg-gray-900 border-2 border-gray-200 dark:border-gray-700 px-6 py-3 rounded-2xl font-bold shadow-strong transform -rotate-3">
<i class="ph ph-star-fill text-yellow-500 mr-2"></i>
4.9/5 Rating
</div>
</div>
</div>
</div>
</section>
<!-- Features Section -->
<section id="features" class="py-24 bg-gradient-to-br from-gray-50 to-white dark:from-gray-800/50 dark:to-gray-900">
<div class="max-w-7xl mx-auto px-6 sm:px-8 lg:px-12">
<div class="text-center mb-20">
<h2 class="text-4xl lg:text-6xl font-bold text-gray-900 dark:text-gray-100 mb-8 leading-tight tracking-tight">
Everything You Need to Stay
<span class="text-primary">Organized</span>
</h2>
<p class="text-xl lg:text-2xl text-gray-600 dark:text-gray-400 leading-relaxed text-pretty max-w-4xl mx-auto">
Trackeep combines all your productivity tools into one seamless experience with powerful features designed for modern workflows
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<FeatureCard
icon="ph ph-bookmark-simple"
title="Bookmarks & Links"
description="Save and categorize web content with smart tags, powerful search, and automatic organization"
/>
<FeatureCard
icon="ph ph-check-square"
title="Task Management"
description="Plan and track your to-dos with customizable workflows, due dates, and priority levels"
/>
<FeatureCard
icon="ph ph-folder-simple"
title="File Storage"
description="Upload and organize documents with version control, sharing, and advanced search"
/>
<FeatureCard
icon="ph ph-sparkle"
title="AI-Powered"
description="Smart recommendations and automated organization with optional AI features"
/>
<FeatureCard
icon="ph ph-shield-check"
title="Privacy First"
description="Self-hosted and secure with end-to-end encryption and complete data control"
/>
<FeatureCard
icon="ph ph-device-mobile"
title="Mobile App"
description="Native iOS and Android apps for on-the-go access and offline support"
/>
</div>
</div>
</section>
<!-- Benefits Section -->
<section class="py-20 bg-white dark:bg-gray-900">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-3xl lg:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">
Why Choose
<span class="text-primary">Trackeep</span>
</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-3xl mx-auto">
The perfect balance of simplicity, privacy, and power
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<div class="text-center">
<div class="bg-primary/10 text-primary w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="ph ph-lock-simple text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-3">Privacy First</h3>
<p class="text-gray-600 dark:text-gray-400">Your data stays yours. No tracking, no data mining, complete control over your information.</p>
</div>
<div class="text-center">
<div class="bg-primary/10 text-primary w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="ph ph-code text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-3">Open Source</h3>
<p class="text-gray-600 dark:text-gray-400">Transparent and customizable. Audit the code, modify features, contribute to the community.</p>
</div>
<div class="text-center">
<div class="bg-primary/10 text-primary w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="ph ph-stack text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-3">All-in-One</h3>
<p class="text-gray-600 dark:text-gray-400">Replace multiple apps with one unified platform for bookmarks, tasks, files, and knowledge.</p>
</div>
<div class="text-center">
<div class="bg-primary/10 text-primary w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="ph ph-sparkle text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-3">AI Optional</h3>
<p class="text-gray-600 dark:text-gray-400">Use AI features when you want them, with full control over what gets processed.</p>
</div>
<div class="text-center">
<div class="bg-primary/10 text-primary w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="ph ph-credit-card text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-3">No Subscriptions</h3>
<p class="text-gray-600 dark:text-gray-400">One-time setup, no monthly fees. Pay for hosting, not for features.</p>
</div>
<div class="text-center">
<div class="bg-primary/10 text-primary w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="ph ph-arrow-counter-clockwise text-2xl"></i>
</div>
<h3 class="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-3">Data Portability</h3>
<p class="text-gray-600 dark:text-gray-400">Export your data anytime. No vendor lock-in, standard formats supported.</p>
</div>
</div>
</div>
</section>
<!-- How It Works Section -->
<section id="how-it-works" class="py-20 bg-white dark:bg-gray-900">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-3xl lg:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">
Get Started in
<span class="text-primary">3 Simple Steps</span>
</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-3xl mx-auto">
From zero to productivity in minutes
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="text-center">
<div class="bg-primary text-white w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4 text-2xl font-bold">
1
</div>
<h3 class="text-xl font-semibold mb-2">Deploy</h3>
<p class="text-gray-600 dark:text-gray-400">Simple Docker setup with one command</p>
</div>
<div class="text-center">
<div class="bg-primary text-white w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4 text-2xl font-bold">
2
</div>
<h3 class="text-xl font-semibold mb-2">Configure</h3>
<p class="text-gray-600 dark:text-gray-400">Set up your preferences and integrations</p>
</div>
<div class="text-center">
<div class="bg-primary text-white w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4 text-2xl font-bold">
3
</div>
<h3 class="text-xl font-semibold mb-2">Use</h3>
<p class="text-gray-600 dark:text-gray-400">Start organizing your digital life</p>
</div>
</div>
</div>
</section>
<!-- Tech Stack Section -->
<section id="tech-stack" class="py-20 bg-gray-50 dark:bg-gray-800/50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-3xl lg:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">
Built with
<span class="text-primary">Modern Technology</span>
</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-3xl mx-auto">
Powered by the best tools for performance and reliability
</p>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-8">
<div class="text-center">
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg p-6 mb-4">
<i class="ph ph-code text-4xl text-primary mb-2"></i>
<h4 class="font-semibold">SolidJS</h4>
<p class="text-sm text-gray-600 dark:text-gray-400">Frontend Framework</p>
</div>
</div>
<div class="text-center">
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg p-6 mb-4">
<i class="ph ph-gear text-4xl text-primary mb-2"></i>
<h4 class="font-semibold">Go</h4>
<p class="text-sm text-gray-600 dark:text-gray-400">Backend Language</p>
</div>
</div>
<div class="text-center">
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg p-6 mb-4">
<i class="ph ph-database text-4xl text-primary mb-2"></i>
<h4 class="font-semibold">PostgreSQL</h4>
<p class="text-sm text-gray-600 dark:text-gray-400">Database</p>
</div>
</div>
<div class="text-center">
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg p-6 mb-4">
<i class="ph ph-devices text-4xl text-primary mb-2"></i>
<h4 class="font-semibold">React Native</h4>
<p class="text-sm text-gray-600 dark:text-gray-400">Mobile Apps</p>
</div>
</div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<section class="py-20 bg-gray-50 dark:bg-gray-800/50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-3xl lg:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">
Loved by
<span class="text-primary">Productivity Enthusiasts</span>
</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-3xl mx-auto">
See what our users are saying about Trackeep
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl p-6 shadow-sm">
<div class="flex items-center mb-4">
<div class="bg-primary/20 text-primary w-10 h-10 rounded-full flex items-center justify-center mr-3">
<i class="ph ph-user"></i>
</div>
<div>
<h4 class="font-semibold text-gray-900 dark:text-gray-100">Sarah Chen</h4>
<p class="text-sm text-gray-600 dark:text-gray-400">Product Manager</p>
</div>
</div>
<p class="text-gray-600 dark:text-gray-400 italic">"Trackeep transformed how I organize my work. Having everything in one place saves me hours every week."</p>
<div class="flex mt-4">
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
</div>
</div>
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl p-6 shadow-sm">
<div class="flex items-center mb-4">
<div class="bg-primary/20 text-primary w-10 h-10 rounded-full flex items-center justify-center mr-3">
<i class="ph ph-user"></i>
</div>
<div>
<h4 class="font-semibold text-gray-900 dark:text-gray-100">Alex Rodriguez</h4>
<p class="text-sm text-gray-600 dark:text-gray-400">Software Developer</p>
</div>
</div>
<p class="text-gray-600 dark:text-gray-400 italic">"Finally, a tool that respects my privacy. Self-hosting means I control my data completely."</p>
<div class="flex mt-4">
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
</div>
</div>
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl p-6 shadow-sm">
<div class="flex items-center mb-4">
<div class="bg-primary/20 text-primary w-10 h-10 rounded-full flex items-center justify-center mr-3">
<i class="ph ph-user"></i>
</div>
<div>
<h4 class="font-semibold text-gray-900 dark:text-gray-100">Emily Watson</h4>
<p class="text-sm text-gray-600 dark:text-gray-400">Content Creator</p>
</div>
</div>
<p class="text-gray-600 dark:text-gray-400 italic">"The AI features are incredible but optional. I love having the choice to use them when needed."</p>
<div class="flex mt-4">
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star-fill text-yellow-500"></i>
<i class="ph ph-star text-yellow-500"></i>
</div>
</div>
</div>
</div>
</section>
<!-- Final CTA Section -->
<section class="py-20 bg-primary">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="text-3xl lg:text-4xl font-bold text-white mb-6">
Ready to Take Control of Your Digital Life?
</h2>
<p class="text-xl text-white/90 mb-8 max-w-3xl mx-auto">
Join thousands of users who have already made the switch to self-hosted productivity.
No subscriptions, no data mining, just pure productivity.
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center mb-8">
<a href="#features" @click="(e) => handleCTAClick(e, 'features')" class="bg-white text-primary px-8 py-4 rounded-lg font-semibold hover:bg-gray-100 transition-colors">
Explore Features
</a>
<a href="https://demo.trackeep.org" target="_blank" class="border-2 border-white text-white px-8 py-4 rounded-lg font-semibold hover:bg-white hover:text-primary transition-colors">
View Live Demo
</a>
</div>
<!-- Quick Install Command -->
<div class="bg-white/10 backdrop-blur-sm border border-white/20 rounded-xl p-6 max-w-2xl mx-auto">
<p class="text-white mb-4 font-medium">Install Trackeep in seconds:</p>
<div class="relative bg-black/20 border border-white/30 rounded-lg p-4">
<code class="text-white text-sm font-mono">curl -sSL https://trackeep.org/install.sh | sh</code>
<button
@click="copyCommand"
class="absolute top-2 right-2 p-2 bg-white/20 hover:bg-white/30 rounded transition-colors"
aria-label="Copy command"
>
<i class="ph ph-copy text-white"></i>
</button>
</div>
</div>
</div>
</section>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import QuickInstall from '../components/QuickInstall.vue'
import FeatureCard from '../components/FeatureCard.vue'
import { useSmoothScroll } from '../composables/useSmoothScroll'
const { scrollToSection } = useSmoothScroll()
const heroImageError = ref(false)
const copyCommand = async () => {
const command = 'curl -sSL https://trackeep.org/install.sh | sh'
try {
await navigator.clipboard.writeText(command)
} catch (err) {
const textArea = document.createElement('textarea')
textArea.value = command
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
}
}
const handleCTAClick = (event: Event, sectionId: string) => {
event.preventDefault()
scrollToSection(sectionId)
}
</script>