# PKM — Flask + Tailwind (v4) + DaisyUI (v5) Personal Knowledge Manager with file-first storage (Markdown + YAML front matter), a minimal Flask backend, and a clean Tailwind + DaisyUI UI. Current milestone: M2 (Rendering and viewing) - Filesystem vault with `notes/`, `attachments/`, and `.kb/` - Create and list notes (M1) - Render Markdown safely with plugins and sanitization (M2) - Obsidian-compatible [[WikiLinks]] (`[[Note]]`, `[[Note|Alias]]`, `[[Note#Heading]]`) - Attachment serving from `/attachments/...` Upcoming (M3) - CodeMirror 6 editor, front matter form, paste/drag image upload --- ## Prerequisites - Python 3.9+ - Node.js 18+ - SQLite (FTS5 needed later in M4; not required yet) --- ## Setup (Python) Create and activate a virtual environment: ```bash python3 -m venv .venv # macOS/Linux source .venv/bin/activate # Windows PowerShell # .venv\Scripts\Activate.ps1 ``` Install Python dependencies: ```bash python3 -m pip install -r requirements.txt # or, if you prefer editable install: python3 -m pip install -e . ``` (Optional) For tests: ```bash python3 -m pip install -e .[dev] ``` --- ## Setup (CSS build with Tailwind v4 + DaisyUI v5) Install Node dev dependencies (uses the Tailwind v4 CLI package): ```bash npm install ``` Build CSS once: ```bash npm run build:css ``` Or keep a watcher running during development: ```bash npm run watch:css ``` This repository uses: - `tailwind.config.js` (ESM) with DaisyUI plugin - `app/static/css/input.css` with: - `@import "tailwindcss";` - `@plugin "daisyui";` If the page looks unstyled, see Troubleshooting below. --- ## Configure your vault You can configure the vault in either of two ways: 1) Environment file - Copy `.env.example` to `.env` and set `KB_VAULT_PATH` to an absolute path. - You can also set `SECRET_KEY` and `FLASK_DEBUG`. ```bash cp .env.example .env # edit .env to set KB_VAULT_PATH=/absolute/path/to/your/vault ``` 2) CLI flags - Pass `--vault /path/to/vault` when running the app (takes precedence over env). --- ## Initialize a vault (optional but recommended) This creates the standard layout and a sample “Welcome” note: ```bash python3 cli.py init --vault /absolute/path/to/vault # Options: # --no-sample Skip creating the sample note # --force Proceed even if the directory is not empty ``` The vault structure will be: ``` / ├─ notes/ ├─ attachments/ └─ .kb/ ├─ config.yml └─ (index.sqlite will be added in M4) ``` --- ## Run the app Using the provided CLI (explicit python3): ```bash python3 cli.py run --vault /absolute/path/to/vault # Options: # --host 127.0.0.1 # --port 5000 # --debug/--no-debug ``` Or, if you set `KB_VAULT_PATH` in `.env`: ```bash python3 cli.py run ``` Open the app at: ``` http://127.0.0.1:5000/ ``` You can: - Create a note at “New Note” - View “Notes” to list them - Use `[[WikiLinks]]` between notes - Reference attachments via `attachments/` (served from `/attachments/...`) --- ## Tests ```bash python3 -m pip install -e .[dev] python3 -m pytest ``` --- ## Troubleshooting (Tailwind/DaisyUI v4) Symptoms: CSS is loaded but the page is unstyled or missing DaisyUI components. Checklist: - Ensure Tailwind v4 CLI is used via npm scripts: - `npm run build:css` (uses `npx @tailwindcss/cli` under the hood as configured) - Confirm ESM config is in place and unique: - Keep only `tailwind.config.js` (remove any `tailwind.config.cjs`) - Confirm input CSS contains: - `@import "tailwindcss";` - `@plugin "daisyui";` - Verify template scan globs match your files: - `content: ["./app/templates/**/*.html", "./app/static/js/**/*.js"]` - Rebuild: - `rm -f app/static/css/app.css && npm run build:css` - Check built CSS for DaisyUI classes: - `grep -n "btn" app/static/css/app.css` If your shell resolves a Ruby `tailwindcss` gem, always invoke via npm scripts (or `npx @tailwindcss/cli`) to ensure the Node CLI runs. --- ## Security notes - Rendered HTML is sanitized with `bleach`; external links are made safe. - Attachments are served with path traversal protection. - For local use, no authentication is enabled yet (planned later if remote hosting is needed). --- ## Project structure (high level) ``` app/ __init__.py # Flask app factory config.py # Env/.env config routes/ home.py # Welcome page notes.py # Notes list/view/create attachments.py # Safe serving of attachments services/ vault.py # Vault paths and structure notes_fs.py # Markdown + YAML read/write renderer.py # Markdown rendering + sanitization + wikilinks utils/ slugs.py # Slug generation time.py # ISO timestamp helpers paths.py # Atomic write & path utilities templates/ ... # Jinja templates (DaisyUI) static/ css/input.css # Tailwind v4 entry (import + plugin) css/app.css # Built output (gitignored) js/app.js # Theme toggle, small helpers cli.py # CLI: init vault, run server ``` --- ## Roadmap - M3: CodeMirror 6 editor, metadata edit form, image paste/drag to `attachments/`. - M4: Indexing/search with SQLite FTS5 under `/.kb/index.sqlite`. - Later: Renames + link rewrites, Git history, command palette, etc. ---