Files
Yutaka Kurosaki 5c338e3ae5 Native locale_names for 14 locales + drop forced-en in editor tabs
Translates the 16-language locale_names block in zh-CN, zh-TW, ko, hi,
vi, tr, de, fr, es, pt-BR, ru, uk, it, pl to the target locale's own
language (e.g. de file: 'en' => 'Englisch', 'ja' => 'Japanisch').

DocumentEditor blade no longer hardcodes 'en' as the locale_names
lookup — falls back to the current UI locale. Test still passes
because tests run with default app locale 'en' and the en file
maps to "Japanese" / "English" etc.

A user editing in ja now sees [English] [日本語 ★] tabs instead of
[English] [Japanese ★].
2026-05-10 13:13:25 +09:00
..
2026-05-09 14:25:12 +09:00
2026-05-09 14:25:12 +09:00

Knowledge Base System

An Obsidian-like knowledge base system built with Laravel 12, Livewire v3, and Alpine.js. Create, organize, and link your documents with wiki-style references and a powerful search interface.

Features

Core Functionality

  • Markdown-based documents with live preview using EasyMDE editor
  • Wiki-style linking with [[Document Title]] syntax
  • Automatic backlinks - see which documents reference the current page
  • Folder organization - use / in titles to auto-organize into folders (e.g., Laravel/Livewire/Components)
  • Quick switcher - Press Ctrl+K to instantly search and navigate
  • Full-text search - MySQL FULLTEXT index with ngram tokenizer for multilingual support
  • ID-based routing - Clean URLs with guaranteed uniqueness

Multi-Language Support

Interface available in 16 languages:

  • English, 日本語 (Japanese)
  • 简体中文, 繁體中文 (Simplified/Traditional Chinese)
  • 한국어 (Korean)
  • हिन्दी (Hindi), Tiếng Việt (Vietnamese), Türkçe (Turkish)
  • Deutsch, Français, Español, Português (Brasil)
  • Русский, Українська, Italiano, Polski

Language preferences persist for both authenticated and guest users via cookies.

Responsive Design

  • Mobile-first interface with hamburger menu
  • Tablet and desktop optimized layouts
  • Touch-friendly navigation
  • All features work seamlessly across devices

User Management

  • Role-based access - Admin and regular user roles
  • User authentication - Laravel Breeze integration
  • Profile management - Update name, email, password, and language preference

Technology Stack

  • Backend: Laravel 12.0 (PHP 8.2+)
  • Frontend: Livewire v3.7.0, Alpine.js, Tailwind CSS
  • Database: MySQL 8.0 with FULLTEXT indexing
  • Markdown: league/commonmark for rendering
  • Editor: EasyMDE (markdown editor)
  • Docker: Custom containerized environment

Prerequisites

  • Docker and Docker Compose
  • Node.js 18+ (for asset compilation)
  • Git

Installation

1. Clone the repository

git clone <repository-url>
cd knowledge-base

2. Start Docker services

docker compose up -d

This starts:

  • Nginx: http://localhost:9700
  • phpMyAdmin: http://localhost:9701
  • MySQL: localhost:9702
  • MailHog: http://localhost:9725

3. Install dependencies

# Inside the src/ directory
cd src

# Install PHP dependencies
docker compose exec php composer install

# Install Node dependencies
npm install

4. Configure environment

# Copy environment file
cp .env.example .env

# Generate application key
docker compose exec php php artisan key:generate

5. Set up database

# Run migrations
docker compose exec php php artisan migrate

# Seed initial user (admin@example.com / password)
docker compose exec php php artisan db:seed --class=UserSeeder

# Initialize sample documents (optional)
docker compose exec php php artisan docs:init

6. Build frontend assets

# Development mode with hot reload
npm run dev

# Or production build
npm run build

7. Access the application

Open http://localhost:9700 in your browser.

Default credentials:

  • Email: admin@example.com
  • Password: password

Development

Running the dev environment

# Start all services (server, queue, logs, Vite)
docker compose exec php composer dev

Running tests

docker compose exec php php artisan test

Common commands

# Access PHP container shell
docker compose exec php bash

# Clear caches
docker compose exec php php artisan config:clear
docker compose exec php php artisan cache:clear
docker compose exec php php artisan view:clear

# Publish Livewire assets (after updates)
docker compose exec php php artisan livewire:publish --assets

Project Structure

src/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   └── LocaleController.php      # Language switching
│   │   └── Middleware/
│   │       └── SetLocale.php              # Multi-language support
│   ├── Livewire/
│   │   ├── DocumentEditor.php             # Create/edit documents
│   │   ├── DocumentViewer.php             # Display documents
│   │   ├── QuickSwitcher.php              # Ctrl+K search modal
│   │   └── SidebarTree.php                # Folder tree navigation
│   ├── Models/
│   │   ├── Document.php                   # Document model
│   │   ├── DocumentLink.php               # Wiki-style links
│   │   └── RecentDocument.php             # Access history
│   └── Services/
│       └── DocumentService.php            # Document business logic
├── database/
│   └── migrations/                        # Database schema
├── lang/                                  # Translation files (16 languages)
├── resources/
│   ├── css/
│   │   └── app.css                        # Tailwind + custom styles
│   ├── js/
│   │   └── app.js                         # Alpine.js initialization
│   └── views/
│       ├── layouts/
│       │   └── knowledge-base.blade.php   # Main layout
│       └── livewire/                      # Livewire component views
└── routes/
    └── web.php                            # Application routes

Key Concepts

Document Organization

Documents are organized using virtual paths derived from titles:

Title: "Laravel/Livewire/Components"
 Path: "Laravel/Livewire/Components.md"
 Slug: "components"
 Sidebar: Nested under Laravel  Livewire  Components

No manual directory field needed - just use / in the title!

Create links between documents using double brackets:

See [[Getting Started]] for more information.
Links to [[Uncreated Pages]] appear in red.

Links are automatically:

  • Extracted and stored in the document_links table
  • Rendered as clickable HTML anchors
  • Displayed as backlinks on target documents

ID-Based Routing

URLs use document IDs instead of slugs:

/documents/123        (instead of /documents/my-document-slug)

Benefits:

  • Guaranteed uniqueness
  • Title changes don't break URLs
  • Simpler route model binding

Folder State Persistence

Sidebar folder expanded/collapsed state is stored in localStorage:

// Managed by Alpine.js
localStorage.getItem('kb_expanded_folders')
// ["Laravel", "Laravel/Livewire", "Docker"]

Survives page navigation and browser sessions.

Customization

Adding new languages

  1. Add to SetLocale::SUPPORTED_LOCALES in app/Http/Middleware/SetLocale.php
  2. Create translation file at lang/{code}/messages.php
  3. Copy structure from existing language file

Changing default locale

Edit config/app.php:

'locale' => 'en',  // Change to your preferred language code

Customizing markdown styles

Edit resources/css/app.css:

@layer components {
    .prose .wiki-link {
        @apply text-indigo-600 hover:text-indigo-800 underline;
    }
}

Troubleshooting

Livewire assets not loading

docker compose exec php php artisan livewire:publish --assets

Frontend changes not reflecting

npm run build
docker compose exec php php artisan view:clear

Database connection errors

Check .env file matches Docker Compose settings:

DB_CONNECTION=mysql
DB_HOST=kb_mysql
DB_PORT=3306
DB_DATABASE=knowledge_base
DB_USERNAME=kb_user
DB_PASSWORD=kb_password

Alpine.js errors in console

Ensure scripts are loaded in correct order in knowledge-base.blade.php:

  1. Livewire scripts first
  2. Alpine.js initialization (via Vite)
  3. Custom Alpine components

Contributing

Contributions are welcome! Please ensure:

  • Code follows Laravel and PSR-12 conventions
  • All existing tests pass
  • New features include tests
  • UI changes maintain responsive design

License

This project is open-sourced software licensed under the MIT license.

Credits

Built with: