Build Dabble

KINDAreplaces $19/mosaves $228/yrback to the verdict

0%0 of 17 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A novel workspace whose hard problems are that the manuscript must survive the application, that plot threads have to stay attached to scenes through reordering and splitting, and that an export has to satisfy a specification before anybody will sell it.

estimated effort multi-daythe files for this build are in the project pack

RuntimeTauri with a React front end and a small Rust file layerStorageOne plain text file per scene with front matter, and SQLite as a rebuildable indexWritesWrite to a temporary file, verify it reads back, then replace, snapshotting firstIdentityStable scene identifiers in the front matter that survive rename, reorder, split and mergeExportA compiled manuscript plus a book file carrying the metadata its specification requires

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why The file layer is where atomic writing and snapshotting live, and it is the part that must not be approximate.

    Get it rustup, then the platform prerequisites listed by the Tauri project. open ↗

    Verify A blank application builds and runs on your machine

  2. installfree

    Why Builds the front end and runs the test suite.

    Get it nodejs.org or your version manager. open ↗

    Verify node --version prints v22 or higher

  3. installfree

    Why Without it the export phase is guesswork, and the file will be rejected by somebody else's upload form instead of by your own build.

    Get it Use the validation tool published for the format and pin its version in the repository.

    Verify A deliberately broken export fails and a good one passes

  4. have readyfree

    Why Every problem in this build is a problem of scale: reordering, orphaned beats, counting disagreements and export timing all look fine on a ten scene fixture.

    Get it Use your own work in progress, or a public domain novel split into scene files.

    Verify Index rebuild, grid render and export all complete within a stated time

  5. decidefree

    Why Deciding it after implementation means the rule is whatever the code happened to do, and the number will disagree with a submission form for reasons nobody can explain.

    Get it Write down how hyphenated compounds, contractions, numerals and dialogue punctuation are treated, then implement that.

    Verify A fixture counts exactly as the document says it should

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- Scene files on disk with front matter(id, title, pov, status, updated_at) · the file is the record and everything else is derived from it
- scene_index(id, path, ordinal, chapter_id, title, words, hash, indexed_at) · rebuilt by rescanning the folder, and safe to delete at any time
- snapshots(id, scene_id, at, path, bytes, reason) · taken before every replace and on a timer, with a stated retention
- threads(id, name, colour, notes) and beats(id, thread_id, scene_id, ordinal, note) · the plot grid, keyed on scene identifier and never on position
- characters(id, name, notes, first_scene_id) and places(id, name, notes) · the continuity notes that a long manuscript cannot hold in one head
- sessions(id, started_at, ended_at, words_start, words_end) · derived from snapshots rather than from a counter that only goes up
- export_runs(id, at, target, output_path, validator_output, state) · including the failures, which are the ones worth reading
- The folder of scene files is the manuscript. Delete the database and everything but the plot grid rebuilds from the files; delete the files and the database is a list of things that no longer exist.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
PROJECT_DIRrequired~/Writing/novelThe folder of scene files. This is the manuscript; everything else is derived.
INDEX_PATHrequired~/Writing/novel/.index.dbThe rebuildable index. Safe to delete at any time.
SNAPSHOT_DIRrequired~/Writing/novel/.snapshotsVersions before every replace. Back this up with the manuscript.
SNAPSHOT_KEEPrequired200Per scene, alongside the age rule. Neither ever removes the newest.
SNAPSHOT_MAX_AGE_DAYSrequired180The age half of the retention rule.
AUTOSAVE_SECONDSrequired20How much typing an unexpected shutdown can cost.
MODEL_API_KEYsecretoptionalsk-...redactedOptional rewrite of a selected passage only. The application works entirely without it.
EXPORT_DIRrequired~/Writing/exportsCompiled manuscripts and book files, with the validator output beside each.

The build, in order

  1. Files first, index second

    The manuscript is a folder of readable files and the database can be thrown away.

    1. The identifier is what everything else will hang from.

      Files src-tauri/src/scenes.rssrc/scenes/frontmatter.ts

    2. Reading it back is the cheap insurance against a truncated write.

      Files src-tauri/src/atomic.rstests/crash.test.ts

    3. An index you are afraid to delete is a second copy of the truth.

      Files src/index/rebuild.ts

    done when · tick each as it passes
    watch out
    • Keeping the manuscript inside a database with an export button means that a failed migration, or a crash during a write, leaves the whole book inside one binary file that no other program can open, and this is the failure that ends writing projects rather than merely annoying people. Put the words in plain files, verify the replacement reads back before it becomes the scene, and make the index something you can delete and rebuild on a Tuesday.
  2. Snapshots, and a way back to Tuesday

    Any scene can be restored to what it said several days ago, byte for byte.

    1. The version you want back is the one that existed before the save.

      Files src/snapshots/take.ts

    2. Both rules, because either alone has a bad day.

      Files src/snapshots/retain.tstests/retention.test.ts

    3. Restoring the wrong version should not be the end of it.

      Files src/snapshots/restore.tstests/restore.test.ts

    done when · tick each as it passes
    watch out
    • An undo stack that lives in memory disappears the moment the application restarts, which is exactly when a writer wants back the paragraph they cut before lunch, and an editor that cannot return it gets replaced by one that can. Snapshot to disk before every replace and on a timer, keep them under a stated retention, and put the restore in the test suite rather than in the documentation.
  3. A plot grid that survives a reorder

    Moving chapter twelve to chapter four leaves every beat where it belongs.

    1. Position is the one property that changes constantly.

      Files src/plot/beats.tstests/reorder.test.ts

    2. Doing it by instinct in the moment gives a different answer each time.

      Files src/plot/split.tsREADME.md

    3. A silently detached beat is worse than a missing one.

      Files src/plot/orphans.ts

    done when · tick each as it passes
    watch out
    • Attaching plot beats to a scene's position in the manuscript means the first structural edit silently invalidates the whole grid, and because it is silent nobody notices until the rewrite, by which point the grid is a picture of a book that no longer exists. Key beats on the scene identifier, decide and document the split and merge rules, and run an orphan report every time the index rebuilds.
  4. Counting words honestly

    One documented counting rule, session totals derived from snapshots, and nothing that shames.

    1. Otherwise the rule is whatever the code happened to do.

      Files docs/word-counting.mdsrc/count.ts

    2. So a day spent cutting reads as a day spent cutting.

      Files src/sessions.tstests/sessions.test.ts

    3. A writing tool that nags is a writing tool people avoid opening.

      Files src/goals.ts

    done when · tick each as it passes
    watch out
    • Every tool counts differently, so a manuscript reading ninety thousand in your editor and eighty seven in a submission form makes the writer distrust both numbers, and a daily total incremented as you type also counts the thousand words you deleted an hour later. Document what the counter counts, derive session figures from the difference between snapshots so a deletion shows as a deletion, and leave goals switched off by default.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more writing tools.