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 98089 additions and 2585 deletions
+336
View File
@@ -0,0 +1,336 @@
# Trackeep Landing Page Plan & Structure
## Project Overview
**Domain**: trackeep.org
**Tech Stack**: Vue 3 + TypeScript + Vite + UnoCSS
**Design System**: Papra-inspired clean UI with Inter font, custom color palette
**Theme**: Dark mode support, no gradients, clean SaaS/PaaS aesthetic
## Design System Reference
### Colors (from existing project)
- **Primary**: `#5BC4F2` (bright blue accent)
- **Background**: Light `#FFFFFF`, Dark `#1A1A1A`
- **Foreground**: Light `#0A0A0A`, Dark `#FAFAFA`
- **Card**: Light `#FCFCFC`, Dark `#1A1A1A`
- **Border**: Light `#E2E8F0`, Dark `#262626`
- **Muted**: Light `#F2F2F2`, Dark `#262626`
### Typography
- **Font**: Inter (400, 500, 600, 700 weights)
- **Sizes**: xs(0.75rem), sm(0.875rem), base(1rem), lg(1.125rem), xl(1.25rem), 2xl(1.5rem), 3xl(1.875rem), 4xl(2.25rem), 6xl(3.75rem)
### Components (reuse from project)
- Papra button variants (`btn-primary`, `btn-secondary`, `btn-outline`)
- Card styles (`card-papra`)
- Navigation items (`nav-item-papra`)
- Transitions (`transition-papra`)
## Landing Page Structure
### 1. Hero Section
**Purpose**: Immediate value proposition and call-to-action
**Components**:
- Navigation bar with logo and menu items
- **Quick Install Command**: Interactive curl command box with copy functionality
- Main headline with subheading
- Primary CTA button
- Hero image placeholder (large, prominent)
- Feature highlights (3-4 key benefits)
**Quick Install Command Section**:
- **Command**: `curl -sSL https://trackeep.org/install.sh | sh`
- **Features**:
- Rounded input box with dark background
- One-click copy functionality
- Syntax highlighting for the command
- Interactive setup script that:
- Checks system requirements (Docker, Docker Compose)
- Downloads latest Trackeep release
- Sets up environment variables
- Initializes database
- Starts all services
- Provides next steps and access URLs
- **Social Proof Buttons**: GitHub and Discord links below the command
**Content Ideas**:
- Headline: "Your Self-Hosted Productivity & Knowledge Hub"
- Subheading: "Track, save, and organize everything that matters to you - all in one place, under your control"
- CTA: "Get Started" or "View Demo"
### 2. Features Section
**Purpose**: Showcase core capabilities
**Layout**: Grid of feature cards (3-4 columns)
**Features to highlight**:
- **Bookmarks & Links**: Save and categorize web content
- **Task Management**: Plan and track your to-dos
- **File Storage**: Upload and organize documents
- **AI-Powered**: Smart recommendations (optional)
- **Privacy First**: Self-hosted and secure
- **Mobile App**: Native iOS and Android
### 3. How It Works Section
**Purpose**: Simple explanation of the setup process
**Steps**:
1. **Deploy**: Simple Docker setup
2. **Configure**: Set up your preferences
3. **Use**: Start organizing your digital life
### 4. Benefits Section
**Purpose**: Why choose Trackeep over alternatives
**Key benefits**:
- **Privacy**: Your data stays yours
- **Open Source**: Transparent and customizable
- **All-in-One**: Replace multiple apps
- **AI Optional**: Use only what you want
- **Self-Hosted**: No subscriptions or data mining
### 5. Tech Stack Section
**Purpose**: Build credibility with developers
**Technologies**:
- **Frontend**: SolidJS, TypeScript, UnoCSS
- **Backend**: Go, PostgreSQL
- **Mobile**: React Native
- **DevOps**: Docker, GitHub Actions
### 6. Pricing Section (if applicable)
**Purpose**: Clear pricing information
**Options**:
- **Free**: Open source, self-hosted
- **Premium**: Optional support/features
- **Enterprise**: Custom solutions
### 7. Testimonials Section
**Purpose**: Social proof
**Layout**: Carousel or grid of user quotes
### 8. Call-to-Action Section
**Purpose**: Final conversion opportunity
**Content**: Strong CTA with benefits summary
### 9. Footer
**Purpose**: Navigation and legal information
**Links**:
- Documentation
- GitHub
- Privacy Policy
- Terms of Service
- Contact
## Technical Implementation Plan
### Project Structure
```
landing/
├── src/
│ ├── components/
│ │ ├── HeroSection.vue
│ │ ├── Navigation.vue
│ │ ├── FeatureCard.vue
│ │ ├── Footer.vue
│ │ ├── QuickInstall.vue
│ │ └── ui/
│ │ ├── Button.vue
│ │ ├── Card.vue
│ │ └── Container.vue
│ ├── composables/
│ │ ├── useTheme.ts
│ │ └── useScroll.ts
│ ├── assets/
│ │ ├── images/
│ │ │ ├── hero-placeholder.png
│ │ │ ├── feature-1.png
│ │ │ ├── feature-2.png
│ │ │ └── feature-3.png
│ │ └── styles/
│ │ └── main.css
│ ├── App.vue
│ ├── main.ts
│ └── router.ts
├── public/
│ ├── favicon.ico
│ └── trackeep-logo.svg
├── package.json
├── vite.config.ts
├── uno.config.ts
└── tsconfig.json
```
### Key Components
#### Navigation Component
- Logo on left
- Menu items center
- Theme toggle right
- Mobile hamburger menu
#### Quick Install Component
- Dark rounded box with command display
- Copy button with clipboard functionality
- Syntax highlighting for curl command
- Success feedback when copied
- GitHub and Discord action buttons
#### Hero Section
- Split layout: text left, image right
- Animated elements on scroll
- Clear CTAs
- Quick install command prominently displayed
#### Feature Cards
- Icon + title + description
- Hover effects
- Consistent spacing
#### Container Component
- Max-width wrapper
- Responsive padding
- Center alignment
### Responsive Design
- **Mobile**: Single column, stacked layout
- **Tablet**: Two-column layouts
- **Desktop**: Full multi-column experience
### Performance Considerations
- Lazy load images
- Optimize fonts (Inter from existing CDN)
- Minimize JavaScript bundle
- Use CSS-in-JS for styling
### SEO Optimization
- Semantic HTML5 structure
- Meta tags for each section
- Structured data markup
- Fast loading times
## Content Strategy
### Messaging Pillars
1. **Simplicity**: Easy to set up and use
2. **Privacy**: Your data, your rules
3. **Flexibility**: Works for individuals and teams
4. **Open Source**: Transparent and community-driven
### Tone of Voice
- Clean and professional
- Approachable and helpful
- Technical but accessible
- Confident but not arrogant
## Image Requirements
### Placeholders needed:
1. **Hero Image**: Large, high-quality dashboard screenshot
2. **Feature Images**: 3-4 illustrations of key features
3. **Tech Stack Logos**: Go, SolidJS, React Native, Docker
4. **Testimonials**: User avatars (optional)
### Image Guidelines:
- Clean, minimalist style
- Consistent color palette
- No gradients (per requirements)
- Dark mode compatible
- Optimized for web (WebP format)
## Development Phases
### Phase 1: Foundation (Week 1)
- Set up Vue + Vite + UnoCSS
- Create basic layout structure
- Implement navigation and footer
- Add theme switching
- **Create QuickInstall component with curl command**
### Phase 2: Content Sections (Week 2)
- Build hero section with install command
- Add features grid
- Create benefits section
- Implement responsive design
### Phase 3: Polish (Week 3)
- Add animations and transitions
- Optimize performance
- SEO implementation
- Cross-browser testing
- **Test install script functionality**
### Phase 4: Launch (Week 4)
- Final content review
- Domain setup
- Analytics integration
- Performance monitoring
- **Deploy install script to trackeep.org/install.sh**
## Success Metrics
- **Page Load Speed**: < 2 seconds
- **Mobile Score**: > 90 on Lighthouse
- **Conversion Rate**: Track demo signups
- **SEO Ranking**: Target keywords positioning
## Next Steps
1. Approve this plan and structure
2. Set up the Vue project with dependencies
3. Create the basic component library
4. **Build QuickInstall component with curl command**
5. Start building sections from top to bottom
6. Integrate with existing design system
7. Add real content and images
8. **Create and deploy the install.sh script**
9. Test and optimize for production
## Install Script Implementation
### install.sh Script Features
```bash
#!/bin/bash
# Interactive Trackeep installation script
# System requirements check
# - Docker & Docker Compose detection
# - OS compatibility (Linux, macOS)
# - Minimum disk space and memory
# Download latest release
# - Fetch from GitHub releases API
# - Verify checksums
# - Extract to /opt/trackeep
# Environment setup
# - Generate secure JWT secret
# - Create .env file with defaults
# - Set up database (SQLite by default)
# Service initialization
# - Start Docker containers
# - Wait for services to be ready
# - Run database migrations
# - Create admin user
# Post-installation
# - Display access URLs
# - Show default credentials
# - Provide next steps
# - Offer demo data import option
```
### Interactive Features
- **Progress indicators** with colored output
- **User prompts** for configuration options
- **Error handling** with helpful messages
- **Rollback capability** if installation fails
- **Update checking** for existing installations
---
This plan leverages your existing design system while creating a professional, modern landing page that showcases Trackeep's value proposition effectively.
Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

+33
View File
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Trackeep - Your Self-Hosted Productivity & Knowledge Hub</title>
<meta name="description" content="Track, save, and organize everything that matters to you - all in one place, under your control. Open source, self-hosted productivity platform." />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://trackeep.org/" />
<meta property="og:title" content="Trackeep - Your Self-Hosted Productivity & Knowledge Hub" />
<meta property="og:description" content="Track, save, and organize everything that matters to you - all in one place, under your control." />
<meta property="og:image" content="https://trackeep.org/og-image.png" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://trackeep.org/" />
<meta property="twitter:title" content="Trackeep - Your Self-Hosted Productivity & Knowledge Hub" />
<meta property="twitter:description" content="Track, save, and organize everything that matters to you - all in one place, under your control." />
<meta property="twitter:image" content="https://trackeep.org/og-image.png" />
<!-- Preconnect to Google Fonts for Inter -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+3186
View File
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
{
"name": "trackeep-landing",
"version": "1.0.0",
"description": "Trackeep Landing Page - Your Self-Hosted Productivity & Knowledge Hub",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
"format": "prettier --write src/"
},
"dependencies": {
"vue": "^3.4.0",
"vue-router": "^4.2.0",
"@vueuse/core": "^10.7.0"
},
"devDependencies": {
"@iconify-json/ph": "^1.1.0",
"@types/node": "^20.10.0",
"@unocss/preset-uno": "^0.58.0",
"@unocss/preset-web-fonts": "^0.58.0",
"@unocss/transformer-directives": "^0.58.0",
"@vitejs/plugin-vue": "^5.0.0",
"typescript": "^5.3.0",
"unocss": "^0.58.0",
"vite": "^5.0.0",
"vue-tsc": "^1.8.0"
},
"engines": {
"node": ">=18.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/trackeep/trackeep.git"
},
"license": "MIT"
}
+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:support@trackeep.org" 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>
+26
View File
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
+11
View File
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"strict": true
},
"include": ["vite.config.ts", "uno.config.ts"]
}
+83
View File
@@ -0,0 +1,83 @@
import {
defineConfig,
presetAttributify,
presetIcons,
presetTypography,
presetUno,
presetWebFonts,
transformerDirectives
} from 'unocss'
export default defineConfig({
presets: [
presetUno(),
presetAttributify(),
presetIcons({
collections: {
ph: '@iconify-json/ph'
}
}),
presetTypography(),
presetWebFonts({
fonts: {
sans: 'Inter:400,500,600,700,800',
mono: 'JetBrains Mono:400,500'
}
})
],
transformers: [
transformerDirectives()
],
theme: {
colors: {
primary: '#5BC4F2',
background: {
light: '#FFFFFF',
dark: '#1A1A1A'
},
foreground: {
light: '#0A0A0A',
dark: '#FAFAFA'
},
card: {
light: '#FCFCFC',
dark: '#1A1A1A'
},
border: {
light: '#E2E8F0',
dark: '#262626'
},
muted: {
light: '#F2F2F2',
dark: '#262626'
}
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace']
},
spacing: {
'18': '4.5rem',
'88': '22rem',
'128': '32rem'
},
borderRadius: {
'4xl': '2rem'
},
boxShadow: {
'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)',
'medium': '0 4px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
'strong': '0 10px 40px -10px rgba(0, 0, 0, 0.15), 0 4px 25px -5px rgba(0, 0, 0, 0.1)'
}
},
shortcuts: {
'btn-primary': 'bg-primary text-white px-8 py-4 rounded-xl font-semibold hover:bg-primary/90 transition-all duration-300 cursor-pointer shadow-soft hover:shadow-medium transform hover:-translate-y-0.5',
'btn-secondary': 'bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 px-8 py-4 rounded-xl font-semibold hover:bg-gray-50 dark:hover:bg-gray-800 transition-all duration-300 cursor-pointer shadow-soft hover:shadow-medium transform hover:-translate-y-0.5',
'btn-outline': 'border-2 border-primary text-primary px-8 py-4 rounded-xl font-semibold hover:bg-primary hover:text-white transition-all duration-300 cursor-pointer transform hover:-translate-y-0.5',
'card-papra': 'bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-2xl p-8 shadow-soft hover:shadow-medium transition-all duration-300',
'nav-item-papra': 'text-gray-700 dark:text-gray-300 hover:text-primary transition-colors duration-200 cursor-pointer font-medium',
'transition-papra': 'transition-all duration-300 ease-out',
'text-balance': 'text-wrap-balance',
'text-pretty': 'text-wrap-pretty'
}
})
+19
View File
@@ -0,0 +1,19 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
vue(),
UnoCSS()
],
resolve: {
alias: {
'@': '/src'
}
},
server: {
port: 3000,
open: true
}
})