Notepad is a Laravel application that started as a shareable notes tool and has been extended into a knowledge workspace with RAG-ready foundations.
Current state:
- Step 1 (Foundation) complete
- Step 2 (AI/RAG) partially complete
The system supports note authoring, notebook-based organization, ingestion of notes/files/URLs, indexing into chunks, notebook-scoped retrieval, and conversational querying with citation metadata.
- Backend: PHP 8.2+, Laravel 12
- Frontend: Blade templates, Bootstrap, jQuery
- Database: MySQL (primary), SQLite (tests)
- Queue: Laravel queues (
syncordatabase) - Parsing/Ingestion:
- URL extraction via HTTP + DOM cleanup
- DOCX extraction via Zip/XML
- PDF extraction via
pdftotextpreferred, parser/fallback chain
- AI Integration:
- Optional OpenAI embeddings/chat
- Deterministic local fallback embeddings and response mode
- Presentation: Blade pages (
resources/views) - HTTP Controllers: request validation, authz, orchestration
- Services: ingestion, chunking, embeddings, retrieval, chat logic
- Jobs: async processing for ingestion/indexing
- Models: notebooks, sources, chunks, conversations, notes
- Ingestion Flow
- User attaches source (
note/file/url) to notebook. sourcerow created/updated.source_ingestionsrow created for file/url.ProcessSourceIngestionjob extracts text.- On success,
source_contentsupdated and source becomesready. IndexSourceChunksjob chunks and embeds content tosource_chunks.
- Chat Flow
- User opens notebook chat.
- User question is stored as a conversation message.
- Retrieval service scores notebook chunks by semantic similarity.
- Chat service generates response using top chunks.
- Assistant response and citations metadata stored in conversation messages.
notes: shareable rich-text notes, optional password, owner metadata.
notebooks: user-owned notebook container.sources: notebook source registry (note/file/url).source_files: uploaded file metadata.source_contents: extracted normalized content.source_ingestions: ingestion attempts and status history.
source_chunks: chunked source text with embedding payload.conversations: notebook conversation threads.conversation_messages: user/assistant messages and metadata.
- Namespaced note routing and legacy redirect compatibility.
- Note security hardening:
- ownership-aware mutations,
- password hashing and migration compatibility,
- read-only fallback for unauthorized editors.
- Notebook CRUD with visibility controls.
- Share-token based notebook sharing.
- Source attachment:
- note,
- URL,
- file (
pdf,doc,docx).
- Source status filtering and retry action.
- Ingestion status tracking and failure capture.
- RAG schema (
source_chunks,conversations,conversation_messages). - Chunking + embedding indexing service and background job.
- Notebook-scoped retrieval service.
- Notebook chat UI and conversation persistence.
- Conversation lifecycle support (new/select/delete).
- Citation metadata persisted for assistant responses.
- OpenAI + local fallback for embedding/chat.
- Notes:
- owner controls mutation,
- password can gate edits for non-owners.
- Notebooks:
- owner-only management and chat.
public/unlistedaccessible by share token in read-only shared view.privatenot accessible via shared link.
- Source actions:
- owner-only attach/retry/remove.
GET /n/{url}show notePOST /n/{url}autosavePUT /n/{url}update note settingsDELETE /n/{url}delete notePOST /n/{url}/passwordunlock note
GET /notebooksindexPOST /notebookscreateGET /notebooks/{id}showPUT /notebooks/{id}updateDELETE /notebooks/{id}deletePOST /notebooks/{id}/share-tokenregenerate share tokenGET /shared/notebooks/{token}shared view
POST /notebooks/{id}/sources/notePOST /notebooks/{id}/sources/filePOST /notebooks/{id}/sources/urlPOST /notebooks/{id}/sources/{source}/retryDELETE /notebooks/{id}/sources/{source}
GET /notebooks/{id}/chatPOST /notebooks/{id}/chatDELETE /notebooks/{id}/chat/{conversation}
APP_KEY- database credentials
QUEUE_CONNECTION=database
OPENAI_API_KEYOPENAI_EMBEDDING_MODEL(defaulttext-embedding-3-small)OPENAI_CHAT_MODEL(defaultgpt-4o-mini)
If OpenAI is unavailable, the app falls back to local deterministic behavior.
cd /Users/imranpollob/Coding/notepad
composer install
npm install
cp .env.example .env
php artisan key:generate
php artisan migratephp artisan serve
php artisan queue:workvendor/bin/phpunitTargeted suites:
vendor/bin/phpunit tests/Feature/NotesSecurityTest.php
vendor/bin/phpunit tests/Feature/NotebookFeaturesTest.php
vendor/bin/phpunit tests/Feature/NotebookIngestionTest.php
vendor/bin/phpunit tests/Feature/NotebookChatTest.php- Visit
/, confirm redirect to/n/{slug}. - Open legacy
/{slug}, confirm redirect to/n/{slug}. - Set password, verify unlock + edit behavior.
- Create notebook.
- Attach note, URL, and file.
- Confirm status transitions and source list updates.
- Trigger failed ingestion and verify retry button flow.
- Open notebook chat.
- Ask a question.
- Confirm conversation appears with user/assistant messages.
- Confirm citations are shown for assistant response.
- Create a second conversation and switch between threads from the conversation list.
- Delete one conversation and confirm it is removed while remaining threads still work.
- Queue worker must run for non-sync processing in production.
- PDF quality varies by source. Scanned image-only PDFs require OCR (not implemented yet).
- Current embeddings are stored as JSON in DB. For scale, move to vector database backend.
- Source-level chat filtering (chat selected sources only).
- Improved citation rendering in answer text.
- Streaming response support.
- Retrieval reranking/hybrid search.
- Vector DB integration (pgvector/Qdrant/Pinecone).
- Shared notebook chat policy and enforcement.
- Observability dashboards for retrieval quality, costs, and latency.