### Start development server Source: https://github.com/streetwriters/notesnook/blob/master/apps/web/README.md Launch the web application in development mode. ```bash npm run start:web ``` -------------------------------- ### Install dependencies Source: https://github.com/streetwriters/notesnook/blob/master/extensions/web-clipper/README.md Run this command in the repository root to install necessary packages. ```sh npm install ``` -------------------------------- ### Install dependencies Source: https://github.com/streetwriters/notesnook/blob/master/apps/web/README.md Prepare the environment by installing required packages using NPM. ```bash # this might take a while to complete npm install ``` -------------------------------- ### Start development server Source: https://github.com/streetwriters/notesnook/blob/master/apps/theme-builder/README.md Launches the theme builder application in development mode. ```bash npm run start:theme-builder ``` -------------------------------- ### Install Dependencies and Bootstrap Mobile Workspace Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Install project dependencies and bootstrap the mobile workspace. This command may take a significant amount of time to complete. ```bash # this might take a while to complete npm install npm run bootstrap -- --scope=mobile ``` -------------------------------- ### Run web clipper Source: https://github.com/streetwriters/notesnook/blob/master/extensions/web-clipper/README.md Start the development build of the web clipper for Chrome. ```sh npm run dev:chrome ``` -------------------------------- ### Run Webapp for Desktop Source: https://github.com/streetwriters/notesnook/blob/master/apps/desktop/README.md Start the web application specifically for the desktop environment. ```bash cd apps/web npm run start:desktop ``` -------------------------------- ### Launch Desktop App Source: https://github.com/streetwriters/notesnook/blob/master/apps/desktop/README.md Start the desktop application from the project root in a separate terminal. ```bash npm run start:desktop ``` -------------------------------- ### Useful Development Commands Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Commands to start the Metro bundler or the Re.Pack bundler independently for development purposes. ```bash # start Metro only npm run start:metro # start Re.Pack bundler npm run start:repack ``` -------------------------------- ### Prepare and Run Notesnook App on iOS Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Install CocoaPods dependencies and then run the Notesnook application on an iOS simulator or physical device. This process may take a while. ```bash # this might take a while to complete npm run prepare:ios npm run start:ios ``` -------------------------------- ### Build and Run iOS E2E Tests Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Build and execute end-to-end tests for the iOS version of the app using Detox. If simulator tooling is missing, install AppleSimulatorUtils via Homebrew. ```bash npm run build:ios npm run test:ios ``` ```bash brew tap wix/brew brew install applesimutils ``` -------------------------------- ### Run Notesnook App on Android Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Start the Notesnook application on an Android emulator or physical device. Ensure an Android emulator is set up or a physical device with USB debugging enabled is connected. ```bash npm run start:android ``` -------------------------------- ### Clone Notesnook Monorepo Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Clone the Notesnook monorepo and navigate into the project directory. Ensure you have Git installed. ```bash git clone https://github.com/streetwriters/notesnook.git # change directory cd notesnook ``` -------------------------------- ### Build and serve production Source: https://github.com/streetwriters/notesnook/blob/master/apps/web/README.md Compile the application for production and serve the build files locally. ```bash npm run build:web # serve the app locally npx serve apps/web/build ``` -------------------------------- ### Get Current Theme Colors in React Source: https://context7.com/streetwriters/notesnook/llms.txt Use the `useThemeColors` hook to access theme colors within a React component. Specify the scope (e.g., 'base', 'editor') to get relevant color palettes. ```typescript import { useThemeColors, useThemeEngineStore, ThemeLight, ThemeDark, validateTheme, themeToCSS } from "@notesnook/theme"; // Get current theme colors in React component function MyComponent() { const { colors, isDark, scope } = useThemeColors("base"); return (
Theme is {isDark ? "dark" : "light"}
); } ``` -------------------------------- ### Build and serve production Source: https://github.com/streetwriters/notesnook/blob/master/apps/theme-builder/README.md Compiles the application for production and serves it locally. ```bash npm run build:theme-builder # serve the app locally npx serve apps/theme-builder/build ``` -------------------------------- ### Example DCO commit message Source: https://github.com/streetwriters/notesnook/blob/master/CONTRIBUTING.md The required format for the Signed-off-by line in commit messages. ```text Signed-off-by: Jane Smith ``` -------------------------------- ### Example commit messages with scopes Source: https://github.com/streetwriters/notesnook/blob/master/CONTRIBUTING.md Commits must include a valid scope prefixing the subject line. Scopes indicate the area of the project affected by the changes. ```text docs: list all valid scopes in commit guidelines ``` ```text web: impl xyz feature ``` ```text crypto: update libsodium version ``` -------------------------------- ### Initialize Application Theme Source: https://github.com/streetwriters/notesnook/blob/master/apps/theme-builder/src/index.html Applies the stored color scheme and theme CSS to the document root on initialization. ```javascript import { themeToCSS } from "@notesnook/theme"; const colorScheme = JSON.parse( window.localStorage.getItem("colorScheme") || '"light"' ); const root = document.querySelector("html"); if (root) root.setAttribute("data-theme", colorScheme); const theme = window.localStorage.getItem(`theme:${colorScheme}`); if (theme) { const css = themeToCSS(JSON.parse(theme)); const stylesheet = document.getElementById("theme-colors"); if (stylesheet) stylesheet.innerHTML = css; } ``` -------------------------------- ### Initialize and Use Logger Source: https://context7.com/streetwriters/notesnook/llms.txt Demonstrates creating a logger instance with a console reporter, logging messages at different levels, creating scoped loggers, and measuring performance. Ensure the reporter is correctly configured. ```typescript import { Logger, NoopLogger, combineReporters, consoleReporter } from "@notesnook/logger"; // Create logger with console reporter const logger = new Logger({ reporter: consoleReporter, lastTime: Date.now() }); // Log at different levels logger.info("Application started"); logger.debug("Debug information", { userId: "123" }); logger.warn("Warning message"); logger.error(new Error("Something went wrong"), "Operation failed"); logger.fatal(new Error("Critical failure"), "System crash"); // Create scoped logger const dbLogger = logger.scope("database"); dbLogger.info("Database connected"); // Logs: [database] Database connected // Measure performance logger.measure("database-query"); // ... perform operation ... logger.measure("database-query"); // Logs: database-query took 150.25ms // Combine multiple reporters const combinedReporter = combineReporters([ consoleReporter, customFileReporter, customNetworkReporter ]); const multiLogger = new Logger({ reporter: combinedReporter, lastTime: Date.now() }); // NoopLogger for testing or disabling logs const noop = new NoopLogger(); noop.info("This won't be logged"); ``` -------------------------------- ### Build Production Packages Source: https://github.com/streetwriters/notesnook/blob/master/apps/desktop/README.md Commands to create final production packages for different operating systems. ```bash npm run release -- --rebuild # For macOS npx electron-builder --config=electron-builder.config.js --mac dmg --arm64 --x64 --publish never # For Linux (AppImage) npx electron-builder --config=electron-builder.config.js --linux AppImage:x64 AppImage:arm64 --publish never # For Windows npx electron-builder --config=electron-builder.config.js --win --publish never ``` -------------------------------- ### Initialize Rich Text Editor with Options Source: https://context7.com/streetwriters/notesnook/llms.txt Initialize the Tiptap-based editor using the `useTiptap` hook. Configure placeholders, date/time formats, and callbacks for various editor functionalities. ```typescript import { useTiptap, Toolbar, getHTMLFromFragment } from "@notesnook/editor"; function NoteEditor() { const editor = useTiptap({ placeholder: "Start writing your note...", // Date/time formatting dateFormat: "MM/DD/YYYY", timeFormat: "12-hour", dayFormat: "short", // Callbacks openLink: (url, newTab) => window.open(url, newTab ? "_blank" : "_self"), downloadAttachment: async (attachment) => { const data = await fetchAttachment(attachment.hash); downloadFile(data, attachment.filename); }, openAttachmentPicker: (type) => { // "image" | "file" | "camera" showFilePicker(type); }, previewAttachment: (attachment) => { showPreviewModal(attachment); }, getAttachmentData: async (attachment) => { return await db.attachments.getData(attachment.hash); }, createInternalLink: async (attributes) => { const selectedNote = await showNotePicker(); return { href: `nn://note/${selectedNote.id}`, title: selectedNote.title }; }, copyToClipboard: (text, html) => { navigator.clipboard.write([ new ClipboardItem({ "text/plain": new Blob([text], { type: "text/plain" }), "text/html": new Blob([html || text], { type: "text/html" }) }) ]); }, // Editor options isMobile: false, doubleSpacedLines: true, enableFontLigatures: true, // Initial content content: "

Initial content here

" }); return (
); } // Get HTML from editor const html = editor.getHTML(); // Get plain text const text = editor.getText(); // Set content editor.commands.setContent("

New content

"); // Insert at cursor editor.commands.insertContent("Bold text"); // Toggle formatting editor.chain().focus().toggleBold().run(); editor.chain().focus().toggleItalic().run(); editor.chain().focus().toggleHeading({ level: 2 }).run(); // Insert special elements editor.chain().focus().insertTable({ rows: 3, cols: 3 }).run(); editor.chain().focus().setCodeBlock({ language: "javascript" }).run(); editor.chain().focus().setTaskList().run(); ``` -------------------------------- ### Run in Release Mode Source: https://github.com/streetwriters/notesnook/blob/master/apps/desktop/README.md Compile and run the application in production mode without generating packages. ```bash npm run staging -- --rebuild ``` -------------------------------- ### Initialize the Notesnook Database Source: https://context7.com/streetwriters/notesnook/llms.txt Configures the Database instance with storage, file system, and SQLite options before initialization. ```typescript import Database from "@notesnook/core"; import { SqliteDialect } from "@streetwriters/kysely"; import BetterSQLite3 from "better-sqlite3-multiple-ciphers"; // Create and configure the database instance const db = new Database(); db.setup({ storage: new NodeStorageInterface(), // Platform-specific storage implementation eventsource: EventSource, // For real-time sync updates fs: new FileStorage(), // File system for attachments compressor: async () => Compressor, // Compression for backups maxNoteVersions: async () => 1000, // Note history limit sqliteOptions: { dialect: (name) => new SqliteDialect({ database: BetterSQLite3(":memory:").unsafeMode(true) }), password: "optional-encryption-password" }, batchSize: 500 }); // Initialize the database (creates tables, runs migrations) await db.init(); console.log("Database initialized:", db.isInitialized); // Output: Database initialized: true ``` -------------------------------- ### Define Application Styles Source: https://github.com/streetwriters/notesnook/blob/master/apps/theme-builder/src/index.html CSS rules for splash screen, skeleton loaders, and layout responsiveness. ```css #splash { display: none !important; } html { overscroll-behavior: none; } html[data-theme="light"] .react-loading-skeleton { --base-color: var(--background-secondary); --highlight-color: #var(--background-secondary); } html[data-theme="dark"] .react-loading-skeleton { --base-color: var(--background-secondary); --highlight-color: var(--background-secondary); } #splash { background-color: var(--background); height: 100%; width: 100%; position: absolute; top: 0; left: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; } #splash svg { transform: scale(1); animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(0.9); } 70% { transform: scale(1); } 100% { transform: scale(0.9); } } html, body { font-size: 16px; } @media only screen and (max-width: 480px) { html, body { font-size: 18px; background-color: var(--background); } } :root, body, #root { margin: 0 !important; height: 100%; overflow: hidden; } #root { display: flex; flex-direction: column; } /* svg { width: 1.5rem; } */ .ReactModal__Overlay { opacity: 0; transition: opacity 200ms ease-in-out; } .ReactModal__Overlay--after-open { opacity: 1; } .ReactModal__Overlay--before-close { opacity: 0; } .slide { background-color: transparent !important; } .carousel.carousel-slider { display: flex; flex-direction: row; } ``` -------------------------------- ### Switch iOS Build Configuration Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/ios/build-configs/README.md Execute this script from the 'apps/mobile' directory to set the active build configuration to 'production' or 'staging'. ```bash bash ios/build-configs/use-ios-build-config.sh production ``` ```bash bash ios/build-configs/use-ios-build-config.sh staging ``` -------------------------------- ### Navigate to web clipper directory Source: https://github.com/streetwriters/notesnook/blob/master/extensions/web-clipper/README.md Change the working directory to the web clipper folder. ```sh cd extensions/web-clipper ``` -------------------------------- ### Build iOS App with Specific Config Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/ios/build-configs/README.md Compile the iOS application directly using a specific configuration file, such as 'ios-build.staging.xcconfig'. ```bash xcodebuild \ -workspace ios/Notesnook.xcworkspace \ -scheme Notesnook \ -configuration Release \ -xcconfig ios/build-configs/ios-build.staging.xcconfig ``` -------------------------------- ### Android Release Commands Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Helper commands for generating release builds of the Notesnook Android application. ```bash npm run release:android npm run release:android:bundle ``` -------------------------------- ### Build iOS App with Active Config Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/ios/build-configs/README.md Use xcodebuild to compile the iOS application, referencing the active configuration file. Ensure you are in the 'apps/mobile' directory. ```bash xcodebuild \ -workspace ios/Notesnook.xcworkspace \ -scheme Notesnook \ -configuration Release \ -xcconfig ios/build-configs/ios-build.active.xcconfig ``` -------------------------------- ### Application CSS Styles Source: https://github.com/streetwriters/notesnook/blob/master/apps/web/src/index.html Global CSS styles for themes, splash screen animations, and layout constraints. ```css html { overscroll-behavior: none; } html[data-theme="light"] .react-loading-skeleton { --base-color: var(--background-secondary); --highlight-color: #var(--background-secondary); } html[data-theme="dark"] .react-loading-skeleton { --base-color: var(--background-secondary); --highlight-color: var(--background-secondary); } #splash { background-color: var(--background); height: 100%; width: 100%; position: absolute; top: 0; left: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; } #splash svg { transform: scale(1); animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(0.9); } 70% { transform: scale(1); } 100% { transform: scale(0.9); } } html, body { font-size: 16px; } @media only screen and (max-width: 480px) { html, body { font-size: 18px; background-color: var(--background); } } :root, body, #root { margin: 0 !important; height: 100%; overflow: hidden; } #root { display: flex; flex-direction: column; } /* svg { width: 1.5rem; } */ .ReactModal__Overlay { opacity: 0; transition: opacity 200ms ease-in-out; } .ReactModal__Overlay--after-open { opacity: 1; } .ReactModal__Overlay--before-close { opacity: 0; } .slide { background-color: transparent !important; } .carousel.carousel-slider { display: flex; flex-direction: row; } ``` -------------------------------- ### Run tests Source: https://github.com/streetwriters/notesnook/blob/master/apps/web/README.md Execute the end-to-end test suite using Playwright. ```bash npm run test:web ``` -------------------------------- ### Build and Run Android E2E Tests Source: https://github.com/streetwriters/notesnook/blob/master/apps/mobile/README.md Build and execute end-to-end tests for the Android version of the app using Detox. Includes commands for both release and debug configurations. ```bash npm run build:android npm run test:android ``` ```bash npm run build:android:debug npm run start:metro npm run test:android:debug ``` -------------------------------- ### Manage Notebooks and Notes Source: https://context7.com/streetwriters/notesnook/llms.txt Create, link, and query notebooks and sub-notebooks. Assign notes to notebooks and manage their hierarchy. Supports operations like pinning, deleting, and retrieving counts. ```typescript // Create a notebook const notebookId = await db.notebooks.add({ title: "Work Projects", description: "All my work-related notes" }); ``` ```typescript // Create a sub-notebook const subNotebookId = await db.notebooks.add({ title: "Q1 2024 Projects" }); ``` ```typescript // Link sub-notebook to parent notebook await db.relations.add( { type: "notebook", id: notebookId }, { type: "notebook", id: subNotebookId } ); ``` ```typescript // Add note to notebook await db.notes.addToNotebook(subNotebookId, noteId); ``` ```typescript // Get all root notebooks (no parent) const rootNotebooks = await db.notebooks.roots.items(); ``` ```typescript // Get all notebooks const allNotebooks = await db.notebooks.all.items(); ``` ```typescript // Get notebook by ID const notebook = await db.notebooks.notebook(notebookId); console.log(notebook?.title); // Output: "Work Projects" ``` ```typescript // Find notebook by title const foundNotebook = await db.notebooks.find("Work Projects"); ``` ```typescript // Get breadcrumbs for navigation const breadcrumbs = await db.notebooks.breadcrumbs(subNotebookId); // Output: [{ id: "...", title: "Work Projects" }, { id: "...", title: "Q1 2024 Projects" }] ``` ```typescript // Get total notes count in notebook (including sub-notebooks) const [totalNotes] = await db.notebooks.totalNotes(notebookId); ``` ```typescript // Get all note IDs in notebook hierarchy const noteIds = await db.notebooks.notes(notebookId); ``` ```typescript // Remove note from notebook await db.notes.removeFromNotebook(notebookId, noteId); ``` ```typescript // Pin notebook await db.notebooks.pin(true, notebookId); ``` ```typescript // Delete notebook (moves to trash) await db.notebooks.moveToTrash(notebookId); ``` -------------------------------- ### Run Prettier code formatter Source: https://github.com/streetwriters/notesnook/blob/master/CONTRIBUTING.md Format your code using Prettier to ensure consistent style. Run this command after making code changes. ```bash npm run prettier ``` -------------------------------- ### Run core tests Source: https://github.com/streetwriters/notesnook/blob/master/packages/core/README.md Execute the Jest test suite to verify the core functionality. ```bash npm run test:core ``` -------------------------------- ### Run ESLint linter Source: https://github.com/streetwriters/notesnook/blob/master/CONTRIBUTING.md Check your code for styling issues using ESLint. This command helps catch most style problems. ```bash npm run lint ``` -------------------------------- ### Create and Process Backups Source: https://context7.com/streetwriters/notesnook/llms.txt Generate encrypted or unencrypted backups of your data using `db.backup.export()`. The export function returns a generator for handling backup chunks, including files and attachments. Use `db.backup.import()` to restore data. ```typescript // Create backup (generator for chunked output) const backupGenerator = db.backup.export({ type: "web", // "web" | "mobile" | "node" encrypt: true, // Encrypt backup with user key mode: "full" // "full" | "partial" }); // Process backup chunks for await (const chunk of backupGenerator) { if (chunk.type === "file") { // Save backup file console.log(`Backup chunk: ${chunk.path}`); await saveFile(chunk.path, chunk.data); } else if (chunk.type === "attachment") { // Handle attachment export console.log(`Attachment ${chunk.current}/${chunk.total}: ${chunk.hash}`); } } // Get last backup time const lastBackupTime = await db.backup.lastBackupTime(); // Restore from backup const backupFile = JSON.parse(backupFileContent); await db.backup.import(backupFile, "user-password"); ``` -------------------------------- ### Manage Notes Collection Source: https://context7.com/streetwriters/notesnook/llms.txt Demonstrates creating, updating, retrieving, organizing, and deleting notes within the Notesnook database. ```typescript // Add a new note with content const noteId = await db.notes.add({ title: "My First Note", content: { type: "tiptap", data: "

Hello, this is my encrypted note content!

" } }); // Retrieve the note const note = await db.notes.note(noteId); console.log(note?.title); // Output: "My First Note" // Get note content const content = await db.content.get(note.contentId); console.log(content?.data); // Output: "

Hello, this is my encrypted note content!

" // Update note properties await db.notes.add({ id: noteId, title: "Updated Title", content: { type: "tiptap", data: "

Updated content with bold text

" } }); // Pin, favorite, and archive notes await db.notes.pin(true, noteId); await db.notes.favorite(true, noteId); await db.notes.archive(true, noteId); // Get all notes with filtering const allNotes = await db.notes.all.items(); const pinnedNotes = await db.notes.pinned.items(); const favoriteNotes = await db.notes.favorites.items(); const archivedNotes = await db.notes.archived.items(); // Export note to different formats const htmlExport = await db.notes.export(noteId, { format: "html" }); const markdownExport = await db.notes.export(noteId, { format: "md" }); const textExport = await db.notes.export(noteId, { format: "txt" }); // Delete note (move to trash) await db.notes.moveToTrash(noteId); // Permanently delete note await db.notes.remove(noteId); ``` -------------------------------- ### StreamableFS File Operations Source: https://context7.com/streetwriters/notesnook/llms.txt Shows how to use StreamableFS for creating, writing, reading, and deleting files in IndexedDB using a streaming interface. Supports chunked operations and provides methods for checking existence, listing, moving, and clearing files. ```typescript import { StreamableFS } from "@notesnook/streamable-fs"; // Create instance with storage backend const fs = new StreamableFS(indexedDBStorage); // Create a new file const fileHandle = await fs.createFile( "document.pdf", 1024000, // size in bytes "application/pdf", { overwrite: true } ); // Write data in chunks const writer = fileHandle.writeable; await writer.write(chunk1); await writer.write(chunk2); await writer.close(); // Read file const readHandle = await fs.readFile("document.pdf"); if (readHandle) { // Get readable stream const reader = readHandle.readable; // Or read as blob const blob = await readHandle.toBlob(); // Get file info console.log(readHandle.file); // Output: { filename: "document.pdf", size: 1024000, type: "application/pdf" } } // Check if file exists const exists = await fs.exists("document.pdf"); // List all files const files = await fs.list(); // Delete file await fs.deleteFile("document.pdf"); // Bulk delete files await fs.bulkDeleteFiles(["file1.pdf", "file2.pdf"]); // Move file const sourceHandle = await fs.readFile("source.pdf"); const destHandle = await fs.createFile("dest.pdf", sourceHandle.file.size, sourceHandle.file.type); await fs.moveFile(sourceHandle, destHandle); // Clear all files await fs.clear(); ```