Fileverse dDocs

August 28, 2026 ยท View on GitHub

ddocs.new is your privacy-focused, open-source alternative to Google Docs. It is an end-to-end encrypted document editor that is optimized for multiplayer collaboration without compromising on speed or people's control over their data.

๐“† Features include:

  • End-to-end encryption
  • Real-time and async collaboration
  • Suggestion mode (tracked changes) and commenting
  • Markdown and LaTeX support
  • MermaidJS diagram support
  • Import/export of .docx, .md, .pdf, .html and more.
  • Dark mode and color themes
  • Offline/online editing (continue writing and opening older docs even with no WiFi)
  • Cross-device syncing (desktop and mobile)
  • Mobile optimized webapp & PWA
  • Private access permissions enabled through zero-knowledge proofs
  • Private social recovery of account/files, enabled through zero-knowledge proofs
  • Version history
  • End-to-end encrypted, programmable API optimised for agents (opt-in)
ddocsNew

This repository contains:

  • /package โ€“ The core package code.
  • Example & demo source code to showcase dDocs functionalities.

Usage

Prequisites

To use dDocs, ensure your project is set up with Tailwind CSS and have a Tailwind configuration file.

Install & import

Add the following imports :

import { DdocEditor } from '@fileverse-dev/ddoc';
import '@fileverse-dev/ddoc/styles'; // in App.jsx/App.tsx

Peer Dependencies

This package requires the following peer dependencies to be installed in your project:

npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities @fileverse/ui @fileverse/crypto viem framer-motion frimousse
PackageVersion
@dnd-kit/core>=6.3.1
@dnd-kit/sortable>=10.0.0
@dnd-kit/utilities>=3.2.2
@fileverse/ui>=5.0.0
@fileverse/crypto>=0.0.21
viem>=2.13.8
framer-motion>=11.2.10
frimousse>=0.3.0

These are externalized from the bundle to avoid duplication when your app already uses them. If you don't have them installed, npm (v7+) will auto-install them for you.

Update Tailwind Config

In your tailwind config, add this line to content array :

@fileverse-dev/ddoc/dist/index.es.js

You should now be set to use dDocs!

dDocProps Interface

The DdocProps interface is a TypeScript interface that defines the properties for a page-related component. It includes properties for handling preview mode, managing publishing data, and optionally storing metadata and content associated with the page.

Core Props

PropertyTypeDescription
initialContentJSONContentInitial content of the editor
onChange(changes: JSONContent, chunk?: any) => voidCallback triggered on editor content changes
refReact.RefObjectReference to access editor instance
isPreviewModebooleanControls if editor is in preview/read-only mode
editorCanvasClassNamesstringAdditional CSS classes for editor canvas
ignoreCorruptedDatabooleanWhether to ignore corrupted data during loading
onInvalidContentError(error: any) => voidCallback for handling invalid content errors

Collaboration Props

PropertyTypeDescription
enableCollaborationbooleanEnables real-time collaboration features
collaborationIdstringUnique ID for collaboration session (required when collaboration enabled)
usernamestringUser's display name for collaboration
setUsername(username: string) => voidFunction to update username
walletAddressstringUser's wallet address
onCollaboratorChange(collaborators?: IDocCollabUsers[]) => voidCallback when collaborators change
enableIndexeddbSyncbooleanEnables IndexedDB sync for offline support
ddocIdstringUnique document ID (required for IndexedDB sync)

UI/UX Props

PropertyTypeDescription
zoomLevelstringCurrent zoom level of the editor
setZoomLevelReact.Dispatch<SetStateAction<string>>Function to update zoom level
isNavbarVisiblebooleanControls navbar visibility
setIsNavbarVisibleReact.Dispatch<SetStateAction<boolean>>Function to toggle navbar visibility
renderNavbar() => JSX.ElementCustom navbar renderer
renderThemeToggle() => JSX.ElementCustom theme toggle renderer
isPresentationModebooleanControls presentation mode
setIsPresentationModeReact.Dispatch<SetStateAction<boolean>>Function to toggle presentation mode
sharedSlidesLinkstringLink for shared presentation slides
documentStylingDocumentStylingCustom styling for document appearance
fontsFontDescriptor[]Consumer-provided font catalog (see Custom Fonts)

Document Styling

The documentStyling prop allows you to customize the visual appearance of your document with three distinct styling areas:

interface ThemeVariantValue {
  light: string;
  dark: string;
}

interface DocumentStyling {
  /**
   * Background styling for the outer document area.
   * Supports CSS background values including gradients.
   * Example: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
   */
  background?: string | ThemeVariantValue;

  /**
   * Background color for the editor canvas/content area.
   * Should be a solid color value.
   * Example: "#ffffff" or "rgb(255, 255, 255)"
   */
  canvasBackground?: string | ThemeVariantValue;

  /**
   * Text color for the editor content.
   * Example: "#333333" or "rgb(51, 51, 51)"
   */
  textColor?: string | ThemeVariantValue;

  /**
   * Font family for the editor content.
   * Example: "Inter, sans-serif" or "'Times New Roman', serif"
   */
  fontFamily?: string;
}

Usage Example

<DdocEditor
  documentStyling={{
    background: {
      light: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
      dark: 'linear-gradient(135deg, #2a3145 0%, #3a2f59 100%)',
    },
    canvasBackground: { light: '#ffffff', dark: '#1e1f22' },
    textColor: { light: '#333333', dark: '#e8ebec' },
    fontFamily: 'Inter, sans-serif',
  }}
  // ... other props
/>

Note: Document styling works in both regular editor mode and presentation mode. In presentation mode, only canvasBackground, textColor, and fontFamily are applied to maintain clean slide appearance.

Custom Fonts

The editor ships with a system-font baseline only (Arial, Calibri, Georgia, Times New Roman, etc.) and makes no third-party font requests โ€” there is no Google Fonts @import. To offer additional fonts, pass a fonts catalog. Each font is self-hosted by your app and loaded on demand via the CSS Font Loading API: a font's woff2 is fetched only when it's selected in the picker or when a document (including a remote collaborator's change) actually renders text in it.

type FontDescriptor = {
  /** Display name shown in the picker, e.g. "Poppins". */
  name: string;
  /** CSS font-family stack stored in the content, e.g. "Poppins, sans-serif". */
  family: string;
  /**
   * woff2 source(s). Omit for a pure system font (no loading).
   *   - string: a single file covering all weights (e.g. a variable font).
   *   - Record<number, string>: a per-weight map, e.g. { 400: url400, 700: url700 }.
   */
  url?: string | Record<number, string>;
  /**
   * Optional SVG preview rendered in the picker. Any React node that renders an
   * <svg>. Falls back to the font name in the default font when absent.
   */
  preview?: React.ReactNode;
};

Usage Example

import { DdocEditor, FontDescriptor } from '@fileverse-dev/ddoc';
// Self-host the woff2 files however your bundler prefers (e.g. @fontsource/*).
import poppins400 from '@fontsource/poppins/files/poppins-latin-400-normal.woff2';
import poppins700 from '@fontsource/poppins/files/poppins-latin-700-normal.woff2';

const fonts: FontDescriptor[] = [
  {
    name: 'Poppins',
    family: 'Poppins, sans-serif',
    url: { 400: poppins400, 700: poppins700 },
    preview: <PoppinsPreview />, // optional SVG
  },
];

<DdocEditor fonts={fonts} /* ...other props */ />;

Notes:

  • The picker lists the system baseline and your catalog together, sorted Aโ€“Z (with Default pinned to the top).
  • The CSS face name is derived from the first token of family, so name is purely cosmetic and can differ (e.g. name: 'Poppins (Brand)', family: 'Poppins, sans-serif').
  • The catalog also drives PDF/print export, which emits @font-face rules for the registered fonts.
  • Host your woff2 files same-origin so they resolve in both the editor and the print iframe.

Comments & Collaboration Props

PropertyTypeDescription
initialCommentsIComment[]Initial comments to display
setInitialComments(comments: IComment[]) => voidFunction to update comments
onCommentReply(id: string, reply: IComment) => voidCallback for comment replies
onNewComment(comment: IComment) => voidCallback for new comments
commentDrawerOpenbooleanControls comment drawer visibility
setCommentDrawerOpen(isOpen: boolean) => voidFunction to toggle comment drawer
onResolveComment(commentId: string) => voidCallback when resolving comments
onUnresolveComment(commentId: string) => voidCallback when unresolving comments
onDeleteComment(commentId: string) => voidCallback when deleting comments
disableInlineCommentbooleanDisables inline commenting feature

Authentication Props

PropertyTypeDescription
isConnectedbooleanUser connection status
isLoadingbooleanAuthentication loading state
connectViaUsername(username: string) => Promise<void>Username-based authentication
connectViaWallet() => Promise<void>Wallet-based authentication
isDDocOwnerbooleanIndicates if user owns the document

Utility Props

PropertyTypeDescription
setCharacterCountReact.Dispatch<SetStateAction<number>>Updates character count
setWordCountReact.Dispatch<SetStateAction<number>>Updates word count
setPageCountReact.Dispatch<SetStateAction<number>>Updates approx. export page count
ensResolutionUrlstringURL for ENS name resolution
ipfsImageUploadFn (file: File) => Promise<IpfsImageUploadResponse>function for secure image uploads
ipfsImageFetchFn (_data: IpfsImageFetchPayload) => Promise<{ url: string;file: File;}>function for fetch secure image from IPFS
onError(error: string) => voidGeneral error handler
onInlineComment() => voidCallback for inline comments
onMarkdownExport() => voidCallback for markdown export
onMarkdownImport() => voidCallback for markdown import
onPdfExport() => voidCallback for pdf export
onSlidesShare() => voidCallback for slides sharing
onComment() => voidGeneral comment callback

Steps to run this example locally

  • npm i
  • npm run dev

It will open up a vite server, that will have the Ddoc Editor.

โš ๏ธ This repository is currently undergoing rapid development, with frequent updates and changes. We recommend not to use in production yet.