1. Getting Started
Tom's Directory Manager is a standalone Windows desktop application for tracking and managing submissions to online directories. It handles the full workflow: keeping a database of directories, managing multiple listings with copy variants, tracking what you've submitted where, and generating a public HTML directory listing page for your own site.
It works for any kind of website or business — software tools, SaaS apps, local businesses, blogs, services, portfolios. If you want to get listed in online directories and need to manage the process at scale, this is the tool for it.
It runs as a single .exe with no installer, no internet requirement for the core app itself, no cloud sync, and no subscriptions. Your data stays on your machine in a local SQLite database.
1.1 System Requirements
Windows 10 or Windows 11, 64-bit. No additional runtime required. An internet connection is needed only for health checks, discovery crawls, and URL imports.
1.2 Installation
- Download the zip from tomdahne.com and extract it to any folder.
- Place
TomDirectoryManager.exeand thedata/folder side by side. - Double-click the exe to launch. No admin rights required. No registry writes.
- The directory list starts empty. Use the Discovery Crawler to build your list — see Section 8.
Tip: Keep the exe and the data/ folder together. The app looks for data files relative to the exe's own location. Moving the exe without the folder will cause missing seed data on a fresh install.
1.3 First Launch
On first launch you will see the main two-panel window. The left panel is Products (the app uses "product" to mean any website or business you're submitting — it can be a SaaS tool, a local business, a blog, anything); the right panel is Directories. The directory list starts empty — there are no pre-loaded directories. You build it yourself by running the Discovery Crawler (see Section 8), which follows source URLs to find directories and lets you review results before anything gets added. The toolbar at the top gives you access to import, export, tools, and settings.
2. The Interface
The app uses a split-panel layout with a resizable divider. The left side is your listings (called "products" in the UI); the right side shows the directory list filtered to whatever you're working on. A toolbar runs across the top, and a status bar at the bottom shows quick counts.
2.1 Left Panel — Products
Lists all your products. Clicking a product selects it and updates the submission stats shown below the list (total directories, submitted count, pending count, coverage percentage). The detail area below the list also shows quick-access combos for selecting which title variant, description variant, and tag set to use during the submission workflow.
2.2 Right Panel — Directories
The main working area. Shows all directories in a sortable listview with columns for name, domain, status, pricing type, auth type, category, domain authority, and last HTTP status. A filter bar across the top of the panel lets you narrow the list by status, pricing type, auth type, and category. A search box filters by name or domain text.
Directory Columns
| Column | What It Shows |
|---|---|
| Name | Display name of the directory |
| Domain | Normalised domain extracted from the directory URL, used for dedup |
| Status | Current submission state — see the status reference below |
| Pricing | Free / Paid / Freemium / Unknown |
| Auth | None / Email / Google / GitHub / etc. |
| Category | Free-text group — Directory, Bookmark, or your own labels |
| DA | Domain authority score if you've populated it |
| HTTP | Last HTTP status code from a health check |
Status Values
| Status | Meaning |
|---|---|
| New | Not yet submitted. Default for all new entries. |
| Pending | Submitted but awaiting approval or review. |
| Submitted | Successfully listed. |
| Dead | Directory is defunct, returns errors, or rejected your listing. |
| Skipped | Deliberately passing on this one (e.g. not relevant, requires payment you don't want to make). |
2.3 Toolbar & Menu
The toolbar provides quick access to the most common actions. The File menu covers imports and exports. The Tools menu has the health checker, blocklist management, and the purge command. The View menu opens the dashboard and the discovery history log.
2.4 Batch Operations
The directory listview supports row checkboxes. Use the Select All and Unselect All buttons to manage the selection, then use the batch action buttons that appear: Delete Selected, Copy URLs. When deleting, a confirmation dialog offers an option to also add the deleted domains to the blocklist — useful for clearing junk directories permanently.
Tip: The Delete key on the keyboard deletes the currently selected (highlighted) row without needing to use the toolbar button.
3. Products (Your Listings)
The app uses the term "product" for whatever you're submitting to directories — it could be a software tool, a SaaS app, a local business, a blog, a service, or any other website. You can manage multiple listings in one place. Each has a core record (name, URL, author details, pricing model) plus a library of text variants for titles, descriptions, and tag sets. Using variants lets you avoid submitting identical copy to every directory, which matters for both SEO diversity and some directories' duplicate-content policies.
3.1 Adding a Product
Click Add Product in the left panel toolbar. The product editor opens to a tabbed dialog with four tabs: Details, Descriptions, Titles, and Tag Sets.
Details Tab
Core fields: Product Name, Product URL, Tagline (one-liner), Author Name, Author Email, Website, GitHub URL, Twitter URL, Pricing Model, Platform, Logo Path, and Short Description. Most directories need at least the name, URL, and a description. Fill in as much as you have — you can always edit later.
Descriptions Tab
Add as many description variants as you want. Each has a label (e.g. "Short 100 words", "Long 250 words") and the text itself. The submission helper tracks how many times each variant has been used so you can rotate through them. If you only add one description, all submissions will use it — that's fine to start.
Titles Tab
Same structure as descriptions. A label and the title text. Different directories may want "Product Name — tagline" vs just "Product Name" vs something more keyword-rich. Add a few variants here.
Tag Sets Tab
Some directories ask for a comma-separated list of tags or keywords. Store your tag sets here with labels. For a local business this might be "Location focus" with tags like sydney, plumber, emergency repairs; for a website it might be "SEO focus" with tags like seo, site audit, crawler, windows.
Tip: In Add mode, everything you type across all four tabs is committed atomically when you click OK. If you close the dialog before clicking OK, nothing is saved. In Edit mode, clicking OK saves everything in one transaction — descriptions, titles, and tag sets all update together.
3.2 Categories
Listings can be assigned to one or more categories using the categories field in the Details tab. This is a free-text multi-value field. Categories help you group listings in reports and filter views. If you're only managing one site, you can leave this blank.
3.3 Selecting Variants for Submission
In the left panel, below the listing list, you'll find three combo boxes: one for the active title variant, one for the active description variant, and one for the active tag set. When you open the submission helper (see Section 5), it pre-populates its fields from whichever variants are currently selected here. Change the selection to rotate your copy.
4. Directories
Directories are the sites you submit to. Each directory record tracks the listing URL, the submission URL (where you go to actually submit), status, pricing type, auth requirement, captcha type, domain authority, notes, category, and source.
4.1 Adding a Directory Manually
Click Add Directory (the + button in the directory panel toolbar) to open the directory editor. Fill in at minimum the name and the listing URL. The submission URL is optional — some directories use the same URL for both browsing and submitting.
URL format: Only http:// and https:// URLs are accepted. If you paste a URL with another scheme (e.g. ftp://), the field will reject it. If you type a bare domain like example.com, the app will automatically prepend https:// when saving.
Directory Fields Reference
| Field | Notes |
|---|---|
| Name | Display name. Shows in the list and in the submission helper. |
| URL | The directory's main listing URL. Used for dedup — the domain is extracted and stored separately to prevent false duplicates. |
| Submission URL | The URL you open to submit. Often different from the listing URL. Optional. |
| Status | New / Pending / Submitted / Dead / Skipped. |
| Pricing Type | Free / Paid / Freemium / Unknown. |
| Auth Type | None / Email / Google / GitHub / Other. |
| Captcha Type | None / reCAPTCHA / hCaptcha / Other. |
| Category | Free-text. Default "Directory". Use "Bookmark" for sites you're tracking but not submitting to. Create your own labels. |
| Domain Authority | Numeric field. Populate manually from Moz/Ahrefs/etc. if you want to sort by DA. |
| Source | How this entry got here. Populated automatically on import and discovery crawl. |
| Notes | Free-text notes. Anything useful: "always use Google login", "approval takes 3 days", etc. |
4.2 Filtering the Directory List
The filter bar at the top of the directory panel has four dropdowns (Status, Pricing, Auth, Category) and a text search box. Filters stack — selecting "Free" pricing AND "New" status shows only free directories you haven't submitted to yet. The search box matches on name and domain text. Clearing all filters shows everything.
4.3 Sorting
Click any column header to sort by that column. Click again to reverse the sort direction. Sorting by Domain Authority (DA) descending is useful for prioritising high-value directories first.
4.4 Deduplication
The app prevents duplicate entries by checking the normalised domain of any URL you add — whether manually, via import, or via the discovery crawler. If example.com is already in your database, trying to add https://www.example.com/page will be treated as a duplicate and silently skipped. This is an exact domain match, not a substring search, so notreallycool.io will not block cool.io.
5. Submission Workflow
The submission workflow is designed for a human manually submitting to each directory in a browser. The app gives you a floating helper window that keeps all your listing copy ready to paste, and tracks your progress through the list.
5.1 The Submission Helper
Select a directory in the list and click Submit (or use the keyboard shortcut) to open the submission helper window. This is a small floating panel that shows:
- The directory name and its submission URL (with an Open button to launch it in your default browser)
- The currently-selected title variant with a Copy button
- The currently-selected description variant with a Copy button
- The currently-selected tag set with a Copy button
- A Mark Submitted button and a Next Unsubmitted button
Drag and Drop
Each text field in the submission helper supports OLE drag-and-drop. You can drag the text directly into browser form fields that accept drag-drop — often faster than copy-pasting, especially when a form has multiple fields open at once.
Variant Selection
The helper shows combo boxes for each of the three text fields (title, description, tag set), so you can switch variants without closing the helper and going back to the product panel. The use count for each variant is tracked — the combos show "Label (used N times)" so you can rotate evenly.
5.2 Mark Submitted
Once you've successfully submitted to a directory, click Mark Submitted in the helper. This changes the directory's status to Submitted and records the submission against the current product, noting which description and title variants were used. The helper then waits for you to click Next Unsubmitted to move to the next directory.
5.3 Next Unsubmitted
Next Unsubmitted advances the directory list selection to the next row with New or Pending status, skipping anything already submitted, dead, or skipped. The helper window updates automatically.
5.4 Mark Dead / Skip
If a directory is defunct or you decide to skip it, use Mark Dead or Skip buttons (or right-click the row in the main list for the context menu). Dead directories stay in the database for record-keeping but are excluded from submission counts. Skipped directories are also excluded from the "pending submissions" denominator in the dashboard.
5.5 Pinning the Helper
The helper window has a pin button (📌) that keeps it on top of all other windows. This is useful when you're alt-tabbing between the app and your browser — the helper stays visible over the browser window so you can read and copy text without switching back to the main window.
6. URL Import
Rather than adding directories one by one, you can bulk-import a list of URLs from a text file or directly from the clipboard. This is the fastest way to load a large list of directories you've curated elsewhere.
6.1 Import from Text File
Go to File → Import URLs from Text File. The file should have one URL per line. Lines starting with # are treated as comments and ignored. The file can have a UTF-8 BOM (which Excel sometimes writes) — this is handled automatically.
6.2 Import from Clipboard
Go to File → Import URLs from Clipboard. Paste your list of URLs first, then trigger the import. Same format as the file import — one URL per line.
6.3 Category Picker
When you trigger either import, a dialog appears showing the number of URLs found and a category combo box. Select a category to assign to all imported rows (default: "Directory"). The combo is seeded with your existing categories plus the defaults (Directory, Bookmark, Other). This can be changed per-row after import if needed.
6.4 What Happens During Import
For each URL in the list the app: strips UTM tracking parameters, validates the URL format, checks if the domain is in the blocklist (skips if so), checks if the domain already exists in the database (skips if so), and inserts the new row with status New and the category you selected. All inserts happen in a single database transaction — either all succeed together or nothing changes.
Tip: The import is domain-based for dedup, not URL-based. If https://example.com/listing and https://example.com/submit are both in your file, only one will be imported because they share the same domain. The first one found wins.
7. Blocklist
The blocklist is a curated set of entries that are silently excluded from all imports and discovery crawls. It has three independent lists: domains, names, and URLs. When any URL is evaluated for import, all three lists are checked.
7.1 What the Blocklist Does
- Domains list: Blocks any URL whose domain matches — including subdomains. So
example.comin the blocklist blockswww.example.com,app.example.com, etc. - Names list: Blocks any entry whose name contains the blocklisted string (case-insensitive).
- URLs list: Blocks exact URL matches.
7.2 Managing the Blocklist
Go to Tools → Manage Blocklist to view and edit the three lists. You can add entries manually or import from the data/blocked_domains.json file. Edits are saved atomically — the app writes to a temporary file first, then renames it over the real file, so a crash mid-write can't corrupt your blocklist.
7.3 Auto-Block on Delete
When you delete a directory (single or bulk), the confirmation dialog includes a checkbox: "Also add deleted domains to blocklist". Checking this adds the domains of all deleted rows to the blocklist immediately, preventing them from coming back in future imports or crawls. Useful after clearing out a batch of junk directories.
7.4 Purge Blocked Entries
Tools → Purge Blocked Entries scans your entire directory database and removes any rows whose domain, name, or URL currently matches the blocklist. This is useful after manually editing the blocklist file to bulk-add domains — run purge once to sweep existing entries out. A confirmation dialog shows the count before you commit.
Note: The seed blocklist at data/blocked_domains.json is a curated list Tom maintains. It's a typed-object JSON format: {"domains":[...], "names":[...], "urls":[...]}. You can edit the file directly — the app will preserve your changes because it only appends to the file, never overwrites it.
8. Discovery Crawler
The Discovery Crawler is how you build your directory list from scratch and keep it growing over time. It follows source URLs — pages like "top directories for X", competitor submission pages, or link aggregators — and extracts every directory it finds. You review the results before anything gets added, so junk never lands in your database without you seeing it first.
Your directory list starts empty. The crawler is step one.
8.1 Discovery Sources
Go to Tools → Discovery Sources to manage your list of seed URLs. Each source has a URL, an active/inactive flag, and tracks the last crawl date and links found. The app ships with a set of pre-configured sources covering common directory aggregators — these are ready to crawl immediately. You can add your own, disable ones that aren't useful, and delete sources you don't want.
8.2 Building Your First List
The best approach when starting out is to crawl one source at a time rather than all at once. A single source typically returns a manageable number of directories — small enough to review properly, mark what's useful, and delete anything that isn't before moving to the next source. Crawling everything at once dumps a large unfiltered batch at you, which is harder to work through.
- Open Tools → Discovery Sources.
- Select one source and click Crawl Selected.
- Review the results in the Review dialog — check the ones worth keeping, uncheck the rest.
- Click Import Selected. The checked URLs are added to your directory list.
- In the main directory list, work through the new entries. Delete anything broken or low-quality — this automatically adds it to the blocklist.
- Repeat with the next source. Previously seen and blocked domains are ignored, so you only see genuinely new results.
Tip: Once your list is established, you can use Crawl All Active to run all sources in one pass. At that point the blocklist is populated and the dedup logic is working, so the results are clean and you only see directories you haven't encountered before.
8.3 How the Crawler Finds Directories
The crawler fetches each source page and extracts URLs using a combination of HTML and Markdown link extraction, anchor text patterns ("submit", "add your site", "get listed", "list your business"), and URL structure analysis. It then filters results against your existing directory list and your blocklist before showing them to you. Only URLs that are genuinely new — not already in your database and not blocked — appear in the review list.
8.4 Deleting Directories Adds Them to the Blocklist
When you delete a directory from your list, its domain is added to the blocklist. This is intentional and important: it means the directory won't appear in future crawl results, even if it keeps showing up in source pages. Over time your blocklist grows to reflect your judgement about which directories aren't worth your time — low quality, defunct, irrelevant to your niche — and the crawler results get progressively cleaner because of it.
The blocklist check runs before results are shown in the Review dialog, so deleted directories don't even show up as "already seen" noise — they're silently excluded. You manage the list by curating it through use, not by manually maintaining a blocklist file.
Note: When deleting in bulk via the batch delete button, the confirmation dialog includes a checkbox: "Also add deleted domains to blocklist". For single-row deletes from the main list this happens automatically. Either way the outcome is the same — gone from the database, blocked from future crawls.
8.5 Crawl History
Go to View → Crawl History to see a log of all past crawls: date, source, links found, new entries added, duplicates skipped, and errors. The last 200 crawl events are shown, newest first. Useful for checking whether a source is consistently producing results or has gone stale.
9. Health Checker
The health checker verifies that your directory URLs are still alive. It sends HTTP HEAD (then GET as fallback) requests to each URL and records the HTTP status code and response time. Useful for periodically sweeping the list and marking dead directories.
9.1 Running a Check
Select one or more directories in the list and click Check Health in the toolbar, or go to Tools → Health Check All to check every directory in your current filtered view. A progress dialog opens showing the check in progress — it runs on background threads so the UI stays usable.
9.2 Results
After the check completes, the HTTP column in the directory list is updated with the last HTTP status code for each checked row. Common results:
| Status | Meaning | Action |
|---|---|---|
200 | OK — site is alive and responding | None needed |
301 / 302 | Redirect — site has moved | Check if it still accepts listings; update URL if needed |
403 | Forbidden — bot blocking | Site is probably alive; visit manually to confirm |
404 | Not found — page is gone | Consider marking as Dead |
500+ | Server error | Wait and re-check; mark Dead if it persists |
| Timeout | No response within the configured timeout | Re-check; consider marking Dead |
9.3 Settings
Health check settings are in the Settings dialog: thread count (how many concurrent checks), timeout in seconds, and whether to follow redirects. The defaults (4 threads, 10 seconds) work well for most use cases. Increase threads for faster bulk checks; decrease if you're hitting rate limits.
10. Dashboard
The dashboard gives you an at-a-glance view of your submission campaign progress. Open it via View → Dashboard.
10.1 What's Shown
- Total directories in the database, broken down by status
- Status breakdown bar chart — visual split of New / Pending / Submitted / Dead / Skipped
- Pricing breakdown bar chart — split of Free / Paid / Freemium / Unknown
- Per-listing submission progress — for each listing, how many directories it's been submitted to vs the total available (Dead and Skipped are excluded from the denominator)
The dashboard is a snapshot of the current database state. Close and reopen it to refresh after making changes.
11. Export & Reports
The app can export your data in several formats for reporting, backup, and public use.
11.1 Export Directories to JSON
Go to File → Export Directories to JSON. Exports all directories (including their category and domain fields) to a JSON array file. Useful for backing up your list or moving it to another machine — import it back via File → Import Directories from JSON.
11.2 Export Submissions to CSV
Go to File → Export Submissions to CSV. Exports every submission record — product, directory, date, status, which description was used — as a UTF-8 CSV file with a BOM so Excel opens it cleanly. Useful for reporting, tracking outreach, or importing into a spreadsheet tracker.
11.3 Export Submissions to HTML Report
Go to File → Export Submissions to HTML. Produces a styled HTML report showing all submissions grouped by product, with directory names, URLs, submission dates, and statuses. Open it in any browser.
11.4 Directory Listing HTML Export
This is the most powerful export. Go to File → Export Directory Listing (HTML) to open the filter dialog. This produces a shareable, SEO-friendly public web page listing your curated directories, ready to publish on your own site.
Filter Dialog Options
| Option | Description |
|---|---|
| Statuses to include | Checkboxes for each status. Typically you'd include Submitted and maybe New, exclude Dead. |
| Pricing types | Include/exclude Free, Paid, Freemium, Unknown directories. |
| Categories | Filter by category — e.g. export only "Directory" entries, not "Bookmark" ones. |
| Sort order | Alphabetical by name, or by domain authority descending. |
| Show submission URLs | Whether to expose the submission URL column publicly. |
What the Output Looks Like
The template (data/directory_listing_template.html) produces a dark-slate themed page matching the tomdahne.com brand: a sticky navigation bar, a hero block with page title and count, directories grouped into sections by pricing type (Free / Free + Paid / Paid / Other), a 3-column responsive grid, and a JSON-LD ItemList schema for Google rich results. The footer includes a "Curated with Tom's Directory Manager" credit.
Tip: You can customise the template by editing data/directory_listing_template.html directly. Keep the marker comments intact (the renderer uses them to inject sections) and you can change any CSS, colours, fonts, or layout you like.
12. Settings
Open settings via Tools → Settings. The dialog is laid out in two columns.
Health Check Settings
- Thread Count: Concurrent health check threads (default 4). More threads = faster checks but higher server load.
- Timeout (seconds): How long to wait for each URL before timing out (default 10).
- Follow Redirects: Whether to follow HTTP 301/302 redirects and record the final status.
Debug Logging
- Enable Debug Log: When on, writes a detailed log to
directorymanager.lognext to the exe. Covers every database operation, migration step, import, crawl, and export. Leave off unless you're troubleshooting something specific. The log is append-only and rotated when it reaches a configured size.
Discovery Settings
- Controls for the discovery crawler's crawl depth, request delay, and max links per source.
Submission Settings
- Default status for new directories. Defaults to "New".
13. Data Files & Backups
Everything the app needs lives in the folder alongside the exe. There is no registry state and no AppData folder. Moving the folder to another machine or drive is a complete backup of all your data.
13.1 The Data Folder
| File | Purpose | Safe to edit? |
|---|---|---|
directorymanager.db | SQLite database — all your listings, directories, and submissions | ❌ App-managed |
directories.json | Optional backup/transfer file — not imported automatically. Use File → Import Directories from JSON to load it manually | ✅ Edit freely |
discovery_sources.json | Seed crawl sources — pre-configured sources ready to crawl on first launch | ✅ Edit freely |
blocked_domains.json | Blocklist (domains, names, URLs) | ✅ App appends only |
directory_listing_template.html | HTML template for the listing export | ✅ Edit freely |
directorymanager.log | Debug log (only present when debug logging is enabled) | ✅ Safe to delete |
13.2 Automatic Backups
The app creates two kinds of automatic backups:
Database Version Backup
On the first launch after a version upgrade, before any database migration runs, the app copies the current database to directorymanager.db.vX_Y_Z.bak (where X_Y_Z is the version you're upgrading from). This means if a migration goes wrong, you have a clean pre-migration copy to restore from. Only one backup per version is created — subsequent launches don't duplicate it.
Blocklist Atomic Write
Every time the blocklist is updated, the app first writes the new content to a temporary file, then snapshots the old content to blocked_domains.json.bak, then renames the temp file over the live file. This means a crash mid-write can never leave you with a corrupted blocklist — you always have either the new file or the backup to restore from.
13.3 Database Schema
The database schema migrates automatically on launch. You should never need to touch the database directly. Migrations are additive (new columns, new tables) and are idempotent — running them twice is safe. The app stores a schema_version in its settings table to track which migrations have run.
14. Technical Notes
A few facts about how the app is built that are worth knowing as a user.
14.1 Single Executable, No Install
The app is a single .exe file with no installer, no registry entries, and no files written outside the folder it lives in. Moving the folder to another machine or drive is a complete migration — nothing is left behind. Deleting the folder removes the app entirely.
14.2 Offline-First
The core app works with no internet connection. An internet connection is only used when you explicitly trigger it: health checks, discovery crawls, and URL imports. Nothing phones home, nothing syncs to a server, nothing requires an account.
14.3 Local Database
All data is stored in a single SQLite database file (directorymanager.db) in the data/ folder. SQLite is a widely-used, battle-tested embedded database format. The file is readable by any SQLite browser if you ever want to inspect or migrate your data directly. The app manages the schema automatically — you never need to touch the database file yourself.
14.4 Background Operations Stay Responsive
Health checks and discovery crawls run on background threads. The main window stays fully usable while they run — you can browse your directory list, edit entries, or open the dashboard while a crawl or health check is in progress. Progress dialogs can be cancelled at any time without data loss.
Single .exe
No installer, no runtime dependencies, no DLLs to manage. Copy and run.
SQLite database
Standard, portable database format. Your data is yours — no proprietary format, no lock-in.
DPI-aware
Scales correctly at 100%, 125%, 150%, and 200% display scaling.
Offline-first
No account required. No data leaves your machine except when you explicitly run a crawl or health check.
15. Troubleshooting
The app won't launch
Make sure you're running the exe on Windows 10 or 11. The app has no additional runtime requirements beyond what Windows provides. If you see an error on launch, check that the data/ folder is present in the same folder as the exe.
The directory list is empty on first launch
That's expected — the app ships with no pre-loaded directories. Use Tools → Discovery Sources to start building your list. Select one source and click Crawl Selected to get your first batch of directories to review and import. See Section 8 for the recommended workflow.
URL Import says "0 imported" even though the file has URLs
All the URLs in your file may already exist in the database (domain dedup), or they may all be in the blocklist. Check the debug log (enable in Settings) for specific "skipped — duplicate" or "skipped — blocklist match" lines.
Health check returns all timeouts
Check your internet connection first. If specific sites are always timing out, they may be blocking bot requests. 403 Forbidden is common for sites with bot protection — these sites are usually alive, the status just reflects the blocking.
The database has duplicate entries
This shouldn't be possible with v1.4.1+ — the directories table has a UNIQUE(url) constraint and the domain-dedup check runs before every insert. If you have duplicates from an older version, the v1.4.1 migration's dedup pass will have already cleaned them up. If you see a suspected duplicate, check the Domain column — entries for the same site but with slightly different URLs (trailing slash, path) will have different domains and may appear together legitimately.
Export produces an empty HTML page
The directory listing export uses your current filter selection in the export filter dialog. Make sure at least one status checkbox is ticked and at least one category is included. If all checkboxes are cleared, an empty filter is treated as "show everything" — but a misconfigured template could also cause this. Check that data/directory_listing_template.html exists and hasn't been edited in a way that removed the section marker comments.
Enabling debug logging for detailed diagnostics
Go to Tools → Settings and turn on Enable Debug Log. Restart the app. A directorymanager.log file will appear next to the exe. This file contains every database operation, migration step, import, crawl, export, and HTTP request — it's very verbose and will tell you exactly where something went wrong. Turn it off again when you're done to avoid accumulating large log files.
Early-init logging: The debug log captures events from the very start of the database open, including migration steps that happen before the settings are read. If you're diagnosing a migration issue, enable debug logging, then force the migration by temporarily renaming your database to make the app think it's a fresh install — the full migration trace will appear in the log on next launch.