A modern, elegant navigation management system built with Vue 3, Material Design 3, and Turso. Simple to configure, beautiful to use, and easy to deploy.
- ๐จ Material Design 3 - Modern, beautiful UI with Vuetify 3
- ๐ Dark Mode - Automatic theme switching
- ๐ Secure Authentication - JWT + bcrypt with HttpOnly cookies
- ๐ฅ Guest Access - Public/private content visibility control
- ๐ฑ Responsive Design - Works perfectly on all devices
- ๐ Edge Deployment - Deploy to Cloudflare Pages or Vercel
- ๐พ Turso Database - Fast, distributed SQLite with Drizzle ORM
- ๐ Type-Safe - Full TypeScript support
- ๐ฆ Import/Export - Easy data migration
- โก Lightning Fast - Built with Vite 6
- Node.js 18+ and pnpm
- A Turso account (free tier available)
cd textus
pnpm install# Install Turso CLI
curl -sSfL https://get.tur.so/install.sh | bash
# Login to Turso
turso auth login
# Create a database
turso db create textus
# Get database URL and auth token
turso db show textus --url
turso db tokens create textusCopy .env.example to .env:
cp .env.example .envEdit .env:
# Turso Database
TURSO_DATABASE_URL=libsql://your-database.turso.io
TURSO_AUTH_TOKEN=your-auth-token
# Authentication
AUTH_ENABLED=true
AUTH_USERNAME=admin
# Generate with: node -e "console.log(require('bcryptjs').hashSync('yourpassword', 10))"
AUTH_PASSWORD=$2a$10$...
AUTH_SECRET=your-jwt-secret-key-min-32-chars
# Guest Access (optional)
AUTH_REQUIRED_FOR_READ=falsenode -e "console.log(require('bcryptjs').hashSync('yourpassword', 10))"Copy the output to AUTH_PASSWORD in .env.
pnpm db:generate
pnpm db:migrateImportant: You need to start both frontend and backend servers!
# Start both frontend and backend (recommended)
pnpm dev:all
# Or start separately
# Terminal 1:
pnpm dev
# Terminal 2:
pnpm dev:apiVisit http://localhost:5173 ๐
๐ก Having issues? Check the detailed Local Development Guide for complete setup steps and troubleshooting.
- Build the project:
pnpm build- Login to Cloudflare:
wrangler login- Create a new Pages project:
wrangler pages project create textus-
Set environment variables in Cloudflare Dashboard:
- Go to Workers & Pages โ Your project โ Settings โ Environment variables
- Add all variables from
.env
-
Deploy:
pnpm deploy:cf- Install Vercel CLI:
pnpm add -g vercel- Login:
vercel login- Set environment variables:
vercel env add TURSO_DATABASE_URL
vercel env add TURSO_AUTH_TOKEN
vercel env add AUTH_ENABLED
vercel env add AUTH_USERNAME
vercel env add AUTH_PASSWORD
vercel env add AUTH_SECRET
vercel env add AUTH_REQUIRED_FOR_READ- Deploy:
pnpm deploy:vercel- AUTH_ENABLED: Enable/disable authentication (
true/false) - AUTH_USERNAME: Admin username
- AUTH_PASSWORD: bcrypt hash of admin password
- AUTH_SECRET: JWT signing secret (min 32 characters)
- AUTH_REQUIRED_FOR_READ: Require auth for viewing content (
true/false)
When AUTH_REQUIRED_FOR_READ=false, unauthenticated users can view content marked as "public". Admins can toggle public/private visibility for each group and site.
- Click "Add Group" to create a navigation category
- Toggle "Public" to make it visible to guests
- Use "Edit Order" to rearrange groups by drag-and-drop
- Click menu (โฎ) on group card to edit or delete
- Click the "+" button on a group card to add a site
- Enter site name, URL, optional icon, and description
- Toggle "Public" to control guest visibility
- Click pencil icon to edit, trash icon to delete
- Export: Click menu (โฎ) โ "Export Data" to download JSON
- Import: Click menu (โฎ) โ "Import Data" to upload JSON
- Import merges data intelligently (groups by name, sites by URL)
textus/
โโโ src/ # Vue 3 frontend
โ โโโ components/ # Vue components
โ โโโ views/ # Page views
โ โโโ stores/ # Pinia stores
โ โโโ utils/ # API client & utilities
โ โโโ styles/ # SASS styles
โ โโโ plugins/ # Vuetify plugin
โ โโโ router/ # Vue Router
โ โโโ types/ # TypeScript types
โโโ server/ # Backend service layer
โ โโโ db/ # Drizzle ORM schema
โ โโโ api/ # API service
โ โโโ utils/ # Auth & validation
โโโ functions/ # Cloudflare Pages Functions
โ โโโ api/ # API routes
โโโ drizzle/ # Generated migrations
โโโ public/ # Static assets
โโโ textus.svg # Logo/Favicon
โโโ manifest.json # PWA manifest
โโโ robots.txt # Search engine directives
โโโ sitemap.xml # Site map
โโโ _headers # Security headers (Netlify/CF)
โโโ .htaccess # Apache configuration
pnpm dev # Start dev server
pnpm build # Build for production
pnpm preview # Preview production build
pnpm typecheck # TypeScript type checking
pnpm lint # Lint code
pnpm format # Format code with Prettier
pnpm db:generate # Generate Drizzle migrations
pnpm db:migrate # Run migrations
pnpm db:studio # Open Drizzle Studio (DB GUI)
pnpm deploy:cf # Deploy to Cloudflare Pages
pnpm deploy:vercel # Deploy to VercelTextus implements comprehensive security measures:
- โ JWT authentication with Web Crypto API (HMAC-SHA256)
- โ bcrypt password hashing (10 rounds)
- โ HttpOnly cookies for token storage (XSS protection)
- โ SQL injection prevention (Drizzle ORM parameterized queries)
- โ CORS with origin whitelist
- โ Login rate limiting (5 attempts per 15 minutes)
- โ Request body size limits (1MB max)
- โ Input validation and sanitization
- โ TypeScript strict mode
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - feel free to use this project for personal or commercial purposes.
- Built with Vue 3
- UI powered by Vuetify 3 (Material Design 3)
- Database by Turso
- ORM by Drizzle
- Icons from Material Design Icons
Made with โค๏ธ and โ by the Textus community
Need help? Found a bug? Open an issue