Skip to content
/ textus Public

Textus is the true successor to browser bookmarks. Beautiful, shareable, cloud-powered visual startpages that finally replace the chaotic 30-year-old bookmark system.

License

Notifications You must be signed in to change notification settings

balmjs/textus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

7 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Textus

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.

Vue 3 Vuetify TypeScript Turso

โœจ Features

  • ๐ŸŽจ 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

๐Ÿš€ Quick Start

Prerequisites

  • Node.js 18+ and pnpm
  • A Turso account (free tier available)

1. Clone and Install

cd textus
pnpm install

2. Set Up Turso Database

# 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 textus

3. Configure Environment

Copy .env.example to .env:

cp .env.example .env

Edit .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=false

4. Generate Password Hash

node -e "console.log(require('bcryptjs').hashSync('yourpassword', 10))"

Copy the output to AUTH_PASSWORD in .env.

5. Run Database Migrations

pnpm db:generate
pnpm db:migrate

6. Start Development Server

Important: 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:api

Visit http://localhost:5173 ๐ŸŽ‰

๐Ÿ’ก Having issues? Check the detailed Local Development Guide for complete setup steps and troubleshooting.

๐Ÿ“ฆ Deployment

Deploy to Cloudflare Pages

  1. Build the project:
pnpm build
  1. Login to Cloudflare:
wrangler login
  1. Create a new Pages project:
wrangler pages project create textus
  1. Set environment variables in Cloudflare Dashboard:

    • Go to Workers & Pages โ†’ Your project โ†’ Settings โ†’ Environment variables
    • Add all variables from .env
  2. Deploy:

pnpm deploy:cf

Deploy to Vercel

  1. Install Vercel CLI:
pnpm add -g vercel
  1. Login:
vercel login
  1. 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
  1. Deploy:
pnpm deploy:vercel

๐Ÿ”ง Configuration

Authentication

  • 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)

Guest Access

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.

๐Ÿ“– Usage

Managing Groups

  1. Click "Add Group" to create a navigation category
  2. Toggle "Public" to make it visible to guests
  3. Use "Edit Order" to rearrange groups by drag-and-drop
  4. Click menu (โ‹ฎ) on group card to edit or delete

Managing Sites

  1. Click the "+" button on a group card to add a site
  2. Enter site name, URL, optional icon, and description
  3. Toggle "Public" to control guest visibility
  4. Click pencil icon to edit, trash icon to delete

Import/Export

  • 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)

๐Ÿ› ๏ธ Development

Project Structure

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

Available Scripts

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 Vercel

๐Ÿ”’ Security

Textus 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

๐Ÿค Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

๐Ÿ“„ License

MIT License - feel free to use this project for personal or commercial purposes.

๐Ÿ™ Acknowledgments


Made with โค๏ธ and โ˜• by the Textus community

Need help? Found a bug? Open an issue

About

Textus is the true successor to browser bookmarks. Beautiful, shareable, cloud-powered visual startpages that finally replace the chaotic 30-year-old bookmark system.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published