Deploying Blinko
Blinko is an AI-powered, self-hosted personal note-taking application that combines the simplicity of quick note capture with the intelligence of advanced AI search and retrieval. Built with TypeScript and designed for privacy-conscious users, Blinko enables you to capture fleeting thoughts, ideas, and information instantly while leveraging artificial intelligence to intelligently search and retrieve your notes using natural language. Whether you’re managing personal notes, project ideas, research notes, or daily reminders, Blinko provides a fast, private, and intelligent note-taking platform under your complete control.
Why Blinko?
Blinko stands out as the premier choice for AI-powered, privacy-focused note-taking with exceptional features and user experience:
- AI-Enhanced Search: Natural language RAG (Retrieval-Augmented Generation) for intelligent note discovery
- Complete Privacy: All notes stored on your servers with zero external data collection
- Self-Hosted: Full control over notes, data, and platform infrastructure
- Fast Capture: Instantly capture ideas and thoughts with minimal friction
- Markdown Support: Full Markdown support for rich text formatting
- Lightweight Architecture: Built with Tauri for efficient, lightweight performance
- Multi-Platform: Native support for macOS, Windows, Linux, Android
- Open Source: Fully transparent code available on GitHub
- Zero Dependencies on Third Parties: No cloud services or external APIs required
- Tag and Categorize: Organize notes with custom tags and collections
- Full-Text Search: Rapid search across entire note library
- Note Sharing: Share notes with specific users or publicly
- Collaboration Features: Real-time collaboration on shared notes
- Mobile-Friendly: Responsive web interface for mobile devices
- API Access: Programmatic access for integrations
- Dark Mode: Beautiful dark interface option
- Keyboard Shortcuts: Power user keyboard shortcuts for efficiency
- Offline Support: Work offline with automatic sync
- Backup and Export: Export notes in multiple formats
- User Management: Multi-user support with role-based access
Blinko is ideal for individuals seeking privacy, teams wanting private knowledge bases, researchers managing notes, students organizing study materials, and anyone preferring intelligent, AI-powered note retrieval. With persistent storage on Klutch.sh, your notes are permanently secure and accessible from anywhere.
Prerequisites
Before deploying Blinko, ensure you have:
- A Klutch.sh account
- A GitHub repository with your Blinko deployment configuration
- Basic familiarity with Docker and Git
- A custom domain name (recommended for production)
- Sufficient storage for your notes (typically 10-50GB based on usage)
- Optional: OpenAI API key for advanced AI features
- Optional: PostgreSQL knowledge for production deployments
Important Considerations
Deploying Blinko
Create a New Project
Log in to your Klutch.sh dashboard and create a new project for your Blinko deployment.
Prepare Your Repository
Create a GitHub repository with the following structure for your Blinko deployment:
blinko-deploy/├─ Dockerfile├─ .env.example├─ docker-entrypoint.sh├─ .gitignore└─ README.mdHere’s a Dockerfile for Blinko:
FROM node:20-alpine# Install system dependenciesRUN apk add --no-cache \curl \git \bash \ca-certificates \postgresql-client# Set working directoryWORKDIR /app# Clone Blinko repositoryRUN git clone https://github.com/blinko-space/blinko.git . && \git checkout main# Install dependencies with bun or npmRUN npm install -g bun && \bun install# Create necessary directoriesRUN mkdir -p /app/data \/app/logs \/app/storage && \chmod -R 755 /app# Build applicationRUN bun run build# Copy entrypoint scriptCOPY docker-entrypoint.sh /RUN chmod +x /docker-entrypoint.sh# Expose portEXPOSE 3010# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \CMD curl -f http://localhost:3010 || exit 1# Run entrypointENTRYPOINT ["/docker-entrypoint.sh"]CMD ["start"]Create a
docker-entrypoint.shfile:#!/bin/bashset -e# Create necessary directoriesmkdir -p /app/data \/app/logs \/app/storage# Set proper permissionschmod -R 755 /app/datachmod -R 755 /app/storage# Check database connection if using PostgreSQLif [ -n "$DATABASE_URL" ]; thenecho "Waiting for database connection..."MAX_ATTEMPTS=30ATTEMPTS=0while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; doif nc -z $(echo $DATABASE_URL | cut -d@ -f2 | cut -d: -f1) \$(echo $DATABASE_URL | cut -d: -f4 | cut -d/ -f1) 2>/dev/null || \pg_isready -h $(echo $DATABASE_URL | cut -d@ -f2 | cut -d: -f1) \-p $(echo $DATABASE_URL | cut -d: -f4 | cut -d/ -f1) 2>/dev/null; thenecho "Database is ready!"breakfiATTEMPTS=$((ATTEMPTS + 1))sleep 1donefi# Run migrations if neededif [ ! -f /app/data/.migrated ]; thenecho "Running database migrations..."bun run prisma migrate deploy || truetouch /app/data/.migratedfiif [ "$1" = "start" ]; then# Start the applicationbun run startelseexec "$@"fiCreate a
.env.examplefile:Terminal window # Blinko ConfigurationNODE_ENV=productionPORT=3010APP_URL=https://notes.yourdomain.com# Database ConfigurationDATABASE_URL=postgresql://blinko:password@db:5432/blinko# AuthenticationJWT_SECRET=your-secure-jwt-secret-hereSESSION_SECRET=your-secure-session-secret-here# Admin UserADMIN_EMAIL=admin@yourdomain.comADMIN_PASSWORD=secure_password_here# Storage ConfigurationSTORAGE_PATH=/app/storageDATA_PATH=/app/dataLOG_PATH=/app/logs# AI Configuration (Optional)ENABLE_AI_SEARCH=trueOPENAI_API_KEY=OPENAI_MODEL=gpt-3.5-turbo# FeaturesENABLE_PUBLIC_SHARING=trueENABLE_COLLABORATION=trueENABLE_TAGS=trueMAX_NOTE_SIZE=10485760# SecurityFORCE_HTTPS=trueSESSION_TIMEOUT_MINUTES=1440# LoggingLOG_LEVEL=infoCommit and push to your GitHub repository:
Terminal window git initgit add .git commit -m "Initial Blinko deployment"git remote add origin https://github.com/yourusername/blinko-deploy.gitgit push -u origin mainCreate a New App
In the Klutch.sh dashboard:
- Click “Create New App”
- Select your GitHub repository containing the Dockerfile
- Choose the branch (typically
mainormaster) - Klutch.sh will automatically detect the Dockerfile in the root directory
Configure Environment Variables
Set up these essential environment variables in your Klutch.sh dashboard:
Variable Description Example NODE_ENVNode environment productionPORTApplication port 3010APP_URLYour application domain https://notes.yourdomain.comDATABASE_URLPostgreSQL connection string postgresql://user:pass@host/dbJWT_SECRETJWT signing secret (generate secure) secure-random-stringSESSION_SECRETSession secret (generate secure) secure-random-stringADMIN_EMAILAdmin account email admin@yourdomain.comADMIN_PASSWORDAdmin account password secure_passwordSTORAGE_PATHPath to note storage /app/storageDATA_PATHPath to application data /app/dataLOG_PATHPath to application logs /app/logsENABLE_AI_SEARCHEnable AI-powered search trueENABLE_PUBLIC_SHARINGAllow note sharing trueENABLE_COLLABORATIONEnable collaborative editing trueFORCE_HTTPSForce HTTPS connections trueLOG_LEVELLogging verbosity infoConfigure Persistent Storage
Blinko requires persistent storage for notes and application data. Add persistent volumes:
Mount Path Description Recommended Size /app/storageNote files and attachments 100GB+ /app/dataDatabase and application data 50GB /app/logsApplication logs 20GB In the Klutch.sh dashboard:
- Navigate to your app settings
- Go to the “Volumes” section
- Click “Add Volume” for each mount path
- Set mount paths and sizes as specified above
Set Network Configuration
Configure your app’s network settings:
- Select traffic type: HTTP (Blinko uses standard web ports)
- Recommended internal port: 3010 (as specified in Dockerfile)
- Klutch.sh will automatically handle HTTPS termination via reverse proxy
- Ensure ports 80 and 443 are accessible from your domain
Configure Custom Domain
Blinko works best with a custom domain for professional note-taking:
- Navigate to your app’s “Domains” section in Klutch.sh
- Click “Add Custom Domain”
- Enter your domain (e.g.,
notes.yourdomain.com) - Configure DNS with a CNAME record to point to your Klutch.sh app
- Update
APP_URLenvironment variable to match your domain - Klutch.sh will automatically provision SSL certificates
Deploy Your App
- Review all settings and environment variables
- Verify all persistent volumes are properly configured
- Click “Deploy”
- Klutch.sh will build the Docker image and start your Blinko instance
- Wait for the deployment to complete (typically 5-10 minutes)
- Access your Blinko instance at your configured domain
- Log in with admin credentials to begin creating notes
Initial Setup and Configuration
After deployment completes, access your Blinko instance to complete setup.
Accessing Blinko
Navigate to your domain: https://notes.yourdomain.com
Log in with the admin credentials you configured in environment variables.
Creating Your First Note
Start capturing ideas and notes:
- Click the ”+” button or “New Note” option
- Enter your note title
- Type your note content with Markdown support
- Add tags for organization (e.g., #ideas, #project, #research)
- Click save to store your note
- Notes are automatically indexed for AI search
Understanding Note Organization
Organize your notes effectively:
- Tags: Add hashtags to categorize notes (#work, #personal, #research)
- Collections: Create collections for grouping related notes
- Starred Notes: Mark important notes as favorites for quick access
- Pinned Notes: Pin frequently accessed notes to top of list
- Search: Use AI-powered natural language search to find notes
Setting Up AI Search
Enable AI-powered note retrieval:
- Navigate to “Settings” → “AI Configuration”
- AI search enabled by default with local embeddings
- Optional: Add OpenAI API key for advanced features
- Log in to your OpenAI account
- Generate API key
- Paste key in Blinko settings
- Test AI search by querying notes naturally
- AI learns from your note patterns over time
Creating User Accounts
Set up accounts for team members:
- Navigate to “Settings” → “Users”
- Click “Invite User”
- Enter email address
- Set user role (Admin, Editor, or Viewer)
- Send invitation link
- User completes account setup
Sharing Notes
Share notes with other users:
- Select a note
- Click “Share” button
- Choose sharing method:
- Share with specific users
- Create public link (optional)
- Set permissions (view only or edit)
- Copy share link and send to recipient
- Recipient can view or edit note
Setting Up Collections
Organize notes into collections:
- Navigate to “Collections” or “Library”
- Click “Create New Collection”
- Name your collection
- Add description
- Add notes to collection by dragging or selecting
- Organize collections hierarchically if needed
Environment Variable Examples
Basic Configuration
NODE_ENV=productionPORT=3010APP_URL=https://notes.yourdomain.comDATABASE_URL=postgresql://blinko:password@db:5432/blinkoJWT_SECRET=secure-random-stringSESSION_SECRET=secure-random-stringADMIN_EMAIL=admin@yourdomain.comADMIN_PASSWORD=secure_passwordComplete Production Configuration
# Application SettingsNODE_ENV=productionPORT=3010APP_URL=https://notes.yourdomain.comLOG_LEVEL=info
# Database ConfigurationDATABASE_URL=postgresql://blinko_user:secure_password@postgres:5432/blinko
# SecurityJWT_SECRET=your-very-secure-jwt-secret-keySESSION_SECRET=your-very-secure-session-secret-keySESSION_TIMEOUT_MINUTES=1440FORCE_HTTPS=true
# Admin ConfigurationADMIN_EMAIL=admin@yourdomain.comADMIN_PASSWORD=secure_admin_password
# Storage ConfigurationSTORAGE_PATH=/app/storageDATA_PATH=/app/dataLOG_PATH=/app/logsMAX_NOTE_SIZE=10485760
# AI ConfigurationENABLE_AI_SEARCH=trueOPENAI_API_KEY=sk-your-openai-api-keyOPENAI_MODEL=gpt-3.5-turbo
# FeaturesENABLE_PUBLIC_SHARING=trueENABLE_COLLABORATION=trueENABLE_TAGS=trueENABLE_EXPORT=true
# PerformanceDATABASE_POOL_SIZE=20CACHE_ENABLED=trueCACHE_TTL=3600
# Logging and MonitoringDEBUG=falseSENTRY_DSN=Sample Code and Getting Started
Python - Blinko API Integration
import requestsimport jsonfrom typing import Optional, List, Dict
class BlinkoClient: def __init__(self, base_url: str, email: str, password: str): self.base_url = base_url.rstrip('/') self.api_url = f'{self.base_url}/api' self.email = email self.password = password self.access_token = None self.login()
def login(self) -> bool: """Authenticate with Blinko API""" try: response = requests.post( f'{self.api_url}/auth/login', json={'email': self.email, 'password': self.password} ) response.raise_for_status() data = response.json() self.access_token = data.get('token') return bool(self.access_token) except requests.exceptions.RequestException as e: print(f"Login failed: {e}") return False
def get_headers(self) -> Dict: """Get request headers with authentication""" return { 'Content-Type': 'application/json', 'Authorization': f'Bearer {self.access_token}' }
def create_note(self, title: str, content: str, tags: List[str] = None) -> Optional[Dict]: """Create a new note""" try: payload = { 'title': title, 'content': content, 'tags': tags or [] } response = requests.post( f'{self.api_url}/notes', headers=self.get_headers(), json=payload ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Error creating note: {e}") return None
def get_note(self, note_id: str) -> Optional[Dict]: """Retrieve a specific note""" try: response = requests.get( f'{self.api_url}/notes/{note_id}', headers=self.get_headers() ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Error retrieving note: {e}") return None
def list_notes(self, limit: int = 50, offset: int = 0) -> Optional[List[Dict]]: """List all notes""" try: response = requests.get( f'{self.api_url}/notes', headers=self.get_headers(), params={'limit': limit, 'offset': offset} ) response.raise_for_status() return response.json().get('data', []) except requests.exceptions.RequestException as e: print(f"Error listing notes: {e}") return None
def search_notes(self, query: str) -> Optional[List[Dict]]: """Search notes using natural language AI search""" try: response = requests.get( f'{self.api_url}/notes/search', headers=self.get_headers(), params={'q': query} ) response.raise_for_status() return response.json().get('data', []) except requests.exceptions.RequestException as e: print(f"Error searching notes: {e}") return None
def update_note(self, note_id: str, title: str = None, content: str = None, tags: List[str] = None) -> Optional[Dict]: """Update an existing note""" try: payload = {} if title: payload['title'] = title if content: payload['content'] = content if tags: payload['tags'] = tags
response = requests.put( f'{self.api_url}/notes/{note_id}', headers=self.get_headers(), json=payload ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Error updating note: {e}") return None
def delete_note(self, note_id: str) -> bool: """Delete a note""" try: response = requests.delete( f'{self.api_url}/notes/{note_id}', headers=self.get_headers() ) response.raise_for_status() return True except requests.exceptions.RequestException as e: print(f"Error deleting note: {e}") return False
def get_tags(self) -> Optional[List[str]]: """Get all tags in the library""" try: response = requests.get( f'{self.api_url}/tags', headers=self.get_headers() ) response.raise_for_status() return response.json().get('data', []) except requests.exceptions.RequestException as e: print(f"Error getting tags: {e}") return None
def create_collection(self, name: str, description: str = '') -> Optional[Dict]: """Create a new collection""" try: payload = { 'name': name, 'description': description } response = requests.post( f'{self.api_url}/collections', headers=self.get_headers(), json=payload ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Error creating collection: {e}") return None
def add_note_to_collection(self, collection_id: str, note_id: str) -> bool: """Add note to collection""" try: payload = {'note_id': note_id} response = requests.post( f'{self.api_url}/collections/{collection_id}/notes', headers=self.get_headers(), json=payload ) response.raise_for_status() return True except requests.exceptions.RequestException as e: print(f"Error adding note to collection: {e}") return False
def export_notes(self, format: str = 'markdown') -> Optional[bytes]: """Export all notes in specified format""" try: response = requests.get( f'{self.api_url}/export', headers=self.get_headers(), params={'format': format} ) response.raise_for_status() return response.content except requests.exceptions.RequestException as e: print(f"Error exporting notes: {e}") return None
# Usage exampleif __name__ == "__main__": client = BlinkoClient('https://notes.yourdomain.com', 'admin@yourdomain.com', 'password')
# Create a note note = client.create_note( 'Project Ideas', '# My Project Ideas\n- Idea 1\n- Idea 2\n- Idea 3', tags=['projects', 'ideas'] ) if note: print(f"Note created: {note['id']}")
# List all notes notes = client.list_notes(limit=10) if notes: print(f"Total notes: {len(notes)}") for note in notes: print(f"- {note['title']}")
# Search notes results = client.search_notes('important projects') print(f"Search results: {results}")
# Get tags tags = client.get_tags() print(f"Available tags: {tags}")
# Create collection collection = client.create_collection('Work Projects', 'Collection of work-related projects') if collection: collection_id = collection['id'] # Add note to collection if note: client.add_note_to_collection(collection_id, note['id'])
# Export notes export_data = client.export_notes(format='markdown') if export_data: with open('notes_backup.md', 'wb') as f: f.write(export_data)JavaScript - Blinko Web Client
const NOTES_API_URL = 'https://notes.yourdomain.com/api';
class BlinkoNoteApp { constructor(email, password) { this.email = email; this.password = password; this.accessToken = null; this.currentNote = null; }
async login() { try { const response = await fetch(`${NOTES_API_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: this.email, password: this.password }) });
if (!response.ok) throw new Error('Login failed'); const data = await response.json(); this.accessToken = data.token; return true; } catch (error) { console.error('Login error:', error); return false; } }
getHeaders() { return { 'Authorization': `Bearer ${this.accessToken}`, 'Content-Type': 'application/json' }; }
async createNote(title, content, tags = []) { try { const response = await fetch(`${NOTES_API_URL}/notes`, { method: 'POST', headers: this.getHeaders(), body: JSON.stringify({ title, content, tags }) });
if (!response.ok) throw new Error('Failed to create note'); return await response.json(); } catch (error) { console.error('Create note error:', error); return null; } }
async listNotes(limit = 50) { try { const response = await fetch( `${NOTES_API_URL}/notes?limit=${limit}`, { headers: this.getHeaders() } );
if (!response.ok) throw new Error('Failed to list notes'); return await response.json(); } catch (error) { console.error('List notes error:', error); return { data: [] }; } }
async searchNotes(query) { try { const response = await fetch( `${NOTES_API_URL}/notes/search?q=${encodeURIComponent(query)}`, { headers: this.getHeaders() } );
if (!response.ok) throw new Error('Search failed'); return await response.json(); } catch (error) { console.error('Search error:', error); return { data: [] }; } }
async updateNote(noteId, updates) { try { const response = await fetch(`${NOTES_API_URL}/notes/${noteId}`, { method: 'PUT', headers: this.getHeaders(), body: JSON.stringify(updates) });
if (!response.ok) throw new Error('Failed to update note'); return await response.json(); } catch (error) { console.error('Update error:', error); return null; } }
async deleteNote(noteId) { try { const response = await fetch(`${NOTES_API_URL}/notes/${noteId}`, { method: 'DELETE', headers: this.getHeaders() });
return response.ok; } catch (error) { console.error('Delete error:', error); return false; } }
async getTags() { try { const response = await fetch(`${NOTES_API_URL}/tags`, { headers: this.getHeaders() });
if (!response.ok) throw new Error('Failed to fetch tags'); return await response.json(); } catch (error) { console.error('Tags fetch error:', error); return { data: [] }; } }
async shareNote(noteId, userEmail, permission = 'view') { try { const response = await fetch( `${NOTES_API_URL}/notes/${noteId}/share`, { method: 'POST', headers: this.getHeaders(), body: JSON.stringify({ email: userEmail, permission: permission }) } );
if (!response.ok) throw new Error('Failed to share note'); return await response.json(); } catch (error) { console.error('Share error:', error); return null; } }
async exportNotes(format = 'markdown') { try { const response = await fetch( `${NOTES_API_URL}/export?format=${format}`, { headers: this.getHeaders() } );
if (!response.ok) throw new Error('Export failed'); return await response.blob(); } catch (error) { console.error('Export error:', error); return null; } }}
// Usage example(async () => { const app = new BlinkoNoteApp('admin@yourdomain.com', 'password');
// Login const loggedIn = await app.login(); if (!loggedIn) { console.error('Failed to login'); return; }
// Create note const note = await app.createNote( 'Meeting Notes', '# Team Meeting\n\n- Discussion point 1\n- Discussion point 2\n- Action items', ['meetings', 'work'] ); console.log('Created note:', note);
// List notes const notes = await app.listNotes(); console.log('All notes:', notes.data);
// Search notes const searchResults = await app.searchNotes('important meeting'); console.log('Search results:', searchResults.data);
// Get tags const tags = await app.getTags(); console.log('Available tags:', tags.data);
// Share note if (note) { const shared = await app.shareNote(note.id, 'colleague@example.com', 'edit'); console.log('Note shared:', shared); }
// Export notes const exportBlob = await app.exportNotes('markdown'); if (exportBlob) { const url = window.URL.createObjectURL(exportBlob); const a = document.createElement('a'); a.href = url; a.download = 'notes_backup.md'; a.click(); }})();cURL - API Integration Examples
# Login to Blinkocurl -X POST https://notes.yourdomain.com/api/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "admin@yourdomain.com", "password": "your-password" }'
# Create a new notecurl -X POST https://notes.yourdomain.com/api/notes \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "title": "My First Note", "content": "# Markdown Note\n\nThis is my first note with **bold** text", "tags": ["idea", "important"] }'
# List all notescurl -X GET "https://notes.yourdomain.com/api/notes?limit=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# Get specific notecurl -X GET https://notes.yourdomain.com/api/notes/{note-id} \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# Search notes with AIcurl -X GET "https://notes.yourdomain.com/api/notes/search?q=important%20projects" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# Update a notecurl -X PUT https://notes.yourdomain.com/api/notes/{note-id} \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "title": "Updated Title", "content": "Updated note content" }'
# Delete a notecurl -X DELETE https://notes.yourdomain.com/api/notes/{note-id} \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# Get all tagscurl -X GET https://notes.yourdomain.com/api/tags \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# Share a notecurl -X POST https://notes.yourdomain.com/api/notes/{note-id}/share \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "email": "colleague@example.com", "permission": "edit" }'
# Export all notescurl -X GET "https://notes.yourdomain.com/api/export?format=markdown" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -o notes_backup.mdBash - Note Backup Script
#!/bin/bash
# Blinko Notes Backup ScriptBACKUP_DIR="/backups/blinko"TIMESTAMP=$(date +%Y%m%d_%H%M%S)RETENTION_DAYS=30API_URL="https://notes.yourdomain.com/api"EMAIL="admin@yourdomain.com"PASSWORD="your-password"
# Create backup directorymkdir -p $BACKUP_DIR
echo "Starting Blinko backup..."
# Get access tokenTOKEN=$(curl -s -X POST $API_URL/auth/login \ -H "Content-Type: application/json" \ -d "{\"email\":\"$EMAIL\",\"password\":\"$PASSWORD\"}" \ | grep -o '"token":"[^"]*' | cut -d'"' -f4)
if [ -z "$TOKEN" ]; then echo "Failed to authenticate" exit 1fi
# Export notes in markdown formatecho "Exporting notes..."curl -s -X GET "$API_URL/export?format=markdown" \ -H "Authorization: Bearer $TOKEN" \ -o $BACKUP_DIR/blinko_notes_$TIMESTAMP.md
# Export notes in JSON formatecho "Exporting notes as JSON..."curl -s -X GET "$API_URL/export?format=json" \ -H "Authorization: Bearer $TOKEN" \ -o $BACKUP_DIR/blinko_notes_$TIMESTAMP.json
# Compress backupstar -czf $BACKUP_DIR/blinko_backup_$TIMESTAMP.tar.gz \ $BACKUP_DIR/blinko_notes_$TIMESTAMP.md \ $BACKUP_DIR/blinko_notes_$TIMESTAMP.json
# Cleanup old backupsecho "Cleaning up old backups..."find $BACKUP_DIR -name "blinko_backup_*" -mtime +$RETENTION_DAYS -deletefind $BACKUP_DIR -name "blinko_notes_*" -mtime +0 -delete
# Backup summaryecho "Backup completed: $TIMESTAMP"ls -lh $BACKUP_DIR | tail -5
# Optional: Upload to cloud storage (S3 example)# aws s3 cp $BACKUP_DIR/blinko_backup_$TIMESTAMP.tar.gz s3://your-bucket/backups/Docker Compose for Local Development
For local testing before deploying to Klutch.sh:
version: '3.8'
services: blinko: image: blinkospace/blinko:latest container_name: blinko-app environment: NODE_ENV: development PORT: 3010 APP_URL: http://localhost:3010 DATABASE_URL: postgresql://blinko:blinko@db:5432/blinko JWT_SECRET: dev-secret-key-change-in-production SESSION_SECRET: dev-session-secret-change-in-production ADMIN_EMAIL: admin@localhost ADMIN_PASSWORD: admin123 STORAGE_PATH: /app/storage DATA_PATH: /app/data LOG_PATH: /app/logs ports: - "3010:3010" volumes: - ./storage:/app/storage - ./data:/app/data - ./logs:/app/logs depends_on: - db restart: unless-stopped
db: image: postgres:15-alpine container_name: blinko-db environment: POSTGRES_USER: blinko POSTGRES_PASSWORD: blinko POSTGRES_DB: blinko ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data restart: unless-stopped
volumes: postgres_data:To run locally:
docker-compose up -dAccess Blinko at http://localhost:3010
Note Management and Organization
Best Practices for Note-Taking
Develop efficient note-taking habits:
- Use Clear Titles: Descriptive titles make notes searchable
- Leverage Tags: Organize with consistent tags (#work, #personal, #research)
- Write in Markdown: Use formatting for better readability
- Regular Reviews: Review and update notes periodically
- Archive Old Notes: Move completed projects to archive collections
- Link Related Notes: Reference other notes for context
- Use Templates: Create templates for recurring note types
Markdown Formatting
Write rich notes with Markdown:
# Main Heading## Subheading### Sub-subheading
**Bold text** and *italic text*
- Bullet point 1- Bullet point 2 - Nested bullet
1. Numbered item2. Another item
<a href="https://example.com" target="_blank" rel="noopener noreferrer">Link text</a>
`inline code` and
\`\`\`code block\`\`\`
| Header 1 | Header 2 ||----------|----------|| Cell 1 | Cell 2 |AI Search Usage
Maximize AI-powered search effectiveness:
- Natural Language: Query in conversational language
- Context Clues: Include relevant context in searches
- Example Searches:
- “meetings with Sarah about Q4 planning”
- “Python code snippets for API calls”
- “Restaurant recommendations from travel notes”
- Search History: Review previous searches for patterns
- Refine Queries: Adjust search terms for better results
User Management and Permissions
Creating User Accounts
Set up multiple users:
- Admin user created during setup
- Invite additional users via email
- Users complete account registration
- Users log in with their credentials
User Roles
Define access levels:
| Role | Permissions |
|---|---|
| Admin | Create users, manage settings, access all notes |
| Editor | Create and edit notes, share notes |
| Viewer | View shared notes only |
Sharing and Collaboration
Collaborate on notes:
- Select note to share
- Click “Share” or “Collaborate”
- Choose sharing method:
- Share with specific users
- Create public link (optional)
- Set permissions (view or edit)
- Collaborators can real-time edit notes
Advanced Features
Setting Up Collections
Organize notes into collections:
- Create collection for project
- Add related notes to collection
- Create nested sub-collections
- Share entire collection with team
- Archive completed collections
Public Sharing
Share notes publicly:
- Enable public sharing in settings
- Click “Make Public” on note
- Copy public link
- Share link on social media or website
- Readers access without login
Export and Backup
Regularly backup your notes:
- Click “Export” in settings
- Choose format (Markdown, JSON, PDF)
- Download exported file
- Store backups securely
- Test restore procedures regularly
API Access
Use Blinko API for integrations:
- Generate API token in settings
- Use token for authentication
- Build custom applications
- Integrate with other services
- Automate note management
Security and Performance
Data Protection
Secure your notes:
- HTTPS enforced for all connections
- Strong passwords enforced
- JWT tokens for API access
- Secure session management
- Regular security updates
Backup and Recovery
Implement backup strategy:
- Automated daily backups
- Store backups in multiple locations
- Test recovery procedures
- Document backup location
- Monitor backup integrity
Database Performance
Optimize for growth:
- Use PostgreSQL for production
- Create database indexes
- Monitor query performance
- Archive old notes
- Regular database maintenance
Troubleshooting
Common Issues and Solutions
Issue: Cannot login to Blinko
Solutions:
- Verify email and password are correct
- Check if user account is created
- Review application logs
- Check database connectivity
- Restart application container
Issue: AI search not working
Troubleshooting:
- Verify AI search is enabled in settings
- Check OpenAI API key if using external AI
- Ensure notes are properly indexed
- Review API logs for errors
- Try manual indexing of notes
Issue: Notes not saving
Solutions:
- Check database connection
- Verify storage permissions
- Monitor disk space
- Review application logs
- Check network connectivity
Issue: Slow performance with many notes
Solutions:
- Switch to PostgreSQL if using SQLite
- Create database indexes
- Archive old notes
- Enable caching
- Monitor system resources
Updating Blinko
To update Blinko to a newer version:
- Read the release notes carefully
- Backup all notes before updating
- Update your Dockerfile:
RUN git checkout latest-version
- Commit and push to GitHub
- Klutch.sh will automatically rebuild
- Test all features after upgrade
- Monitor logs for any issues
Use Cases
Personal Note-Taking
- Capture daily ideas and thoughts
- Create personal knowledge base
- Quick reference for information
- Daily journal and reflections
Professional Documentation
- Project notes and documentation
- Team meeting notes
- Technical snippets and solutions
- Knowledge sharing with team
Research and Learning
- Research notes and citations
- Learning notes from courses
- Article summaries and highlights
- Reference material organization
Creative Projects
- Story ideas and plot notes
- Character development
- Brainstorming sessions
- Writing drafts and outlines
Additional Resources
- Blinko GitHub Repository - Source code and documentation
- Blinko Official Documentation - Complete guides and API reference
- Blinko Live Demo - Try demo account
- Blinko Official Website - Project information and updates
- Blinko Telegram Community - Community support and discussions
- Klutch.sh Getting Started Guide
- Klutch.sh Volumes Documentation
- Klutch.sh Custom Domains Guide
Conclusion
Deploying Blinko on Klutch.sh provides you with a completely private, AI-powered note-taking platform that maintains full control over your personal knowledge base. With intelligent natural language search, complete privacy, multi-user support, note sharing, and collaborative editing, Blinko enables you to capture and organize ideas effortlessly while leveraging AI to find exactly what you need. Klutch.sh’s managed infrastructure ensures your notes are always available, secure, and performant, allowing you to focus on capturing and organizing your thoughts.
Start hosting your private AI-powered note-taking platform today by deploying Blinko on Klutch.sh and transform how you capture, organize, and retrieve your ideas.