diff --git a/src/app/workspace.rs b/src/app/workspace.rs index 2aa621b..bd2c074 100644 --- a/src/app/workspace.rs +++ b/src/app/workspace.rs @@ -96,7 +96,7 @@ impl App { self.build_story_bible_index(); self.autocomplete = None; self.collapsed.clear(); - // Ensure the manuscript folder (e.g., 06-First Draft) is always expanded + // Ensure the manuscript folder (e.g., 05-First Draft) is always expanded if let Some(ref dir) = self.manuscript_dir { self.collapsed.remove(dir); } @@ -284,7 +284,7 @@ impl App { /// if so, which of its subfolders is the manuscript. /// /// The test is simply whether it has a child folder named like the - /// configured manuscript folder (`06-First Draft`), matched leniently by + /// configured manuscript folder (`05-First Draft`), matched leniently by /// [`order::dir_matches`]. `None` means the workspace is itself the /// manuscript, which is how the app behaved before project mode and remains /// the right answer for a plain folder of chapters. @@ -453,12 +453,23 @@ impl App { } } - /// Lift the header out of the buffer, leaving the prose. Does nothing for a - /// document with no draft marker — there is nothing to collapse. + /// Lift the header out of the buffer, leaving the prose. Supports both + /// YAML frontmatter (`---` delimiters) and the legacy draft marker. pub(super) fn collapse_header(&mut self) { if self.header_stash.is_some() { return; } + + // Try YAML frontmatter first + if let Some((header, body)) = crate::preprocess::split_yaml_frontmatter(&self.buffer) { + let (header, body) = (header.to_string(), body.to_string()); + self.header_stash = Some(header); + self.buffer = body; + self.after_view_change(); + return; + } + + // Fall back to draft marker let Some((header, body)) = crate::preprocess::split_at_marker(&self.buffer, &self.config.draft_marker) else { @@ -639,8 +650,8 @@ impl App { self.rebuild_field_names(); } - /// Create a scene pair: both a planning file (in 05-Plot) and a draft file - /// (in 06-First Draft), linked to each other. Used for the "New Scene" button. + /// Create a new scene file with merged YAML frontmatter containing both + /// planning metadata and draft content. Used for the "New Scene" button. pub(super) fn create_scene_pair(&mut self) { use super::today_utc; @@ -652,24 +663,15 @@ impl App { .unwrap_or_default(); // Check if we're in a First Draft folder (Act 1, Act 2, etc.) - let in_draft_folder = current_dir.starts_with("06-First Draft/Act") - || current_dir.starts_with("06-First Draft/"); - - // Check if we're in a Plot folder (act_1, act_2, etc.) - let in_plot_folder = current_dir.starts_with("05-Plot/act_") - || current_dir.starts_with("05-Plot/"); + let in_draft_folder = current_dir.starts_with("05-First Draft/Act") + || current_dir.starts_with("05-First Draft/"); // Extract act number from current directory let act_num = if in_draft_folder { - // Parse "06-First Draft/Act N" or "06-First Draft/Act N/" + // Parse "05-First Draft/Act N" or "05-First Draft/Act N/" current_dir.split('/').nth(1).and_then(|s| { s.strip_prefix("Act ").and_then(|n| n.parse::().ok()) }) - } else if in_plot_folder { - // Parse "05-Plot/act_N" or "05-Plot/act_N/" - current_dir.split('/').nth(1).and_then(|s| { - s.strip_prefix("act_").and_then(|n| n.parse::().ok()) - }) } else { // Default to Act 1 Some(1) @@ -682,14 +684,14 @@ impl App { let existing_scenes: Vec = self.files.iter() .filter(|f| { let path_lower = f.to_lowercase(); - if in_draft_folder || in_plot_folder { + if in_draft_folder { // Check files in current act - path_lower.contains(&format!("act_{}/", act)) + path_lower.contains(&format!("act {}/", act)) || path_lower.contains(&format!("Act {}/", act)) } else { - // Check both folders - path_lower.contains(&format!("act_{}/scene_", act)) - || path_lower.contains(&format!("Act {}/scene", act)) + // Check files in 05-First Draft + path_lower.contains(&format!("05-first draft/act {}/scene", act)) + || path_lower.contains(&format!("05-first draft/Act {}/scene", act)) } }) .filter_map(|f| { @@ -709,17 +711,17 @@ impl App { let title = format!("Chapter {}: Scene {}", chapter, scene_num); let slug = format!("chapter-{}--scene-{}", chapter, scene_num); - // Determine where to create files - let draft_dir = format!("06-First Draft/Act {}", act); - let plot_dir = format!("05-Plot/act_{:02}", act); + // Determine where to create file + let draft_dir = format!("05-First Draft/Act {}", act); - // Create planning file - let planning_name = format!("{}/scene_{:02}.md", plot_dir, scene_num); - let draft_name = format!("{}/scene{:02}.md", draft_dir, scene_num); + // Scene file + let filename = format!("{}/scene{:02}.md", draft_dir, scene_num); - // Planning file content - let planning_id = format!("scene_{:02}_{:02}_{:02}", act, chapter, scene_num); - let planning_content = format!(r#"--- + // Scene ID + let scene_id = format!("scene_{:02}_{:02}_{:02}", act, chapter, scene_num); + + // Create merged file with YAML frontmatter + let content = format!(r#"--- id: {} title: "{}" slug: {} @@ -727,7 +729,7 @@ act: {} chapter: {} scene: {} type: scene -status: planning +status: draft word_count_target: 2000 word_count_min: 1800 word_count_max: 2200 @@ -739,50 +741,75 @@ time: "" conflict: "" theme: "" tone: "" +word_count: 0 +word_count_updated: "" +session_word_count: 0 +last_session: "" +total_sessions: 0 +version: 1 +created: "{}" +updated: "{}" order: {} -created: "{}" -updated: "{}" --- # {} -**Planning Template** | **ID:** {} | **Status:** Planning +**Scene File** | **ID:** {} | **Status:** Draft --- -## Scene Planning +## Scene Metadata -### The Setup +| Attribute | Value | +|-----------|-------| +| **Act** | {} | +| **Chapter** | {} | +| **Scene** | {} | +| **Type** | Scene | +| **POV** | Not set | +| **Version** | 1 | +| **Word Count Target** | 2000 | -### The Reveal - -### Things to Note - -"#, - planning_id, title, slug, act, chapter, scene_num, - scene_num, - today, today, - title, planning_id - ); - - // Draft file content - let draft_id = format!("draft_scene_{:02}_{:02}_{:02}", act, chapter, scene_num); - let draft_content = format!(r#"--- -id: {} -title: "{}" -slug: {} -type: draft -status: not_started -act: {} -chapter: {} -scene: {} -created: "{}" -updated: "{}" --- -# {} +## Word Count Tracking -**Draft File** | **ID:** {} +| Metric | Value | +|--------|-------| +| **Target** | 2000 | +| **Minimum** | 1800 | +| **Maximum** | 2200 | +| **Current** | 0 | +| **This Session** | 0 | +| **Last Updated** | Never | + +--- + +## Creative Elements + +### POV +> Not specified + +### Characters + +### Setting +> Not specified + +### Date & Time +> Not specified | Not specified + +--- + +## Story Structure + +### Conflict +> Not specified + +### Theme +> Not specified + +### Tone +> Not specified --- @@ -792,20 +819,50 @@ updated: "{}" [Write your scene content here...] +--- + +## Writing Notes + +### Session Log +| Date | Words Added | Notes | +|------|--------------|-------| + + +### Revision Notes +- +- + +--- + +## Status Checklist + +- [ ] Planning complete +- [ ] First draft complete +- [ ] Word count target met +- [ ] POV consistent +- [ ] Character voices distinct +- [ ] Setting details accurate +- [ ] Conflict resolved/advanced +- [ ] Ready for revision + +--- + +**Created:** {} | **Updated:** {} "#, - draft_id, title, slug, - act, chapter, scene_num, + scene_id, title, slug, act, chapter, scene_num, + scene_num, today, today, - title, draft_id + title, scene_id, + act, chapter, scene_num, + today, today ); - // Create both files - self.insert_new_file(planning_name, planning_content); - self.insert_new_file(draft_name.clone(), draft_content); + // Create the merged file + self.insert_new_file(filename.clone(), content); - // Select the draft file (more likely what user wants to edit) - let draft_idx = self.files.iter().position(|f| *f == draft_name).unwrap_or(0); - self.selected = Some(draft_idx); + // Select the new file + let file_idx = self.files.iter().position(|f| *f == filename).unwrap_or(0); + self.selected = Some(file_idx); self.buffer.clear(); self.dirty = false; } @@ -1923,7 +1980,7 @@ mod tests { /// shapes a workspace can take. #[test] fn the_project_root_is_the_folder_the_manuscript_sits_in() { - let ws = Path::new("/books/My Book/06-First Draft"); + let ws = Path::new("/books/My Book/05-First Draft"); let project = Path::new("/books/My Book"); // Project mode: the workspace already is the project root, so an @@ -2183,10 +2240,10 @@ mod tests { let files = v(&[ "00-Scratch Pad/Generated plot points.md", "03-Characters/ada.md", - "06-First Draft/Act 1/scene01.md", - "06-First Draft/draft_v1.md", + "05-First Draft/Act 1/scene01.md", + "05-First Draft/draft_v1.md", ]); - assert_eq!(first_listed(&files, Some("06-First Draft")), Some(2)); + assert_eq!(first_listed(&files, Some("05-First Draft")), Some(2)); } #[test] @@ -2201,33 +2258,33 @@ mod tests { #[test] fn an_empty_manuscript_falls_back_to_the_first_file() { let files = v(&["00-Scratch Pad/note.md", "03-Characters/ada.md"]); - assert_eq!(first_listed(&files, Some("06-First Draft")), Some(0)); + assert_eq!(first_listed(&files, Some("05-First Draft")), Some(0)); } #[test] fn after_a_removal_the_next_listed_file_is_chosen() { let files = v(&[ "00-Scratch Pad/note.md", - "06-First Draft/a.md", - "06-First Draft/b.md", + "05-First Draft/a.md", + "05-First Draft/b.md", ]); // Removing index 1 leaves the following manuscript file at index 1. - assert_eq!(nearest_listed(&files, Some("06-First Draft"), 1), Some(1)); + assert_eq!(nearest_listed(&files, Some("05-First Draft"), 1), Some(1)); // Removing the last one falls back to the previous manuscript file. - assert_eq!(nearest_listed(&files, Some("06-First Draft"), 3), Some(2)); + assert_eq!(nearest_listed(&files, Some("05-First Draft"), 3), Some(2)); } #[test] fn a_removal_never_lands_on_a_reference_file() { - let files = v(&["00-Scratch Pad/note.md", "06-First Draft/a.md"]); + let files = v(&["00-Scratch Pad/note.md", "05-First Draft/a.md"]); // Index 2 is past the end; the search back must skip the scratch pad. - assert_eq!(nearest_listed(&files, Some("06-First Draft"), 2), Some(1)); + assert_eq!(nearest_listed(&files, Some("05-First Draft"), 2), Some(1)); } #[test] fn removing_the_only_manuscript_file_still_selects_something() { let files = v(&["00-Scratch Pad/note.md"]); - assert_eq!(nearest_listed(&files, Some("06-First Draft"), 0), Some(0)); - assert_eq!(nearest_listed(&[], Some("06-First Draft"), 0), None); + assert_eq!(nearest_listed(&files, Some("05-First Draft"), 0), Some(0)); + assert_eq!(nearest_listed(&[], Some("05-First Draft"), 0), None); } } diff --git a/src/config.rs b/src/config.rs index 2da2181..c26bc4a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -191,8 +191,9 @@ pub fn default_project_template() -> PathBuf { /// Default subfolder opened after generating a project: the snowflake /// template's drafting folder, where the chapter files live. +/// Supports both "05-First Draft" (merged planning+draft) and "06-First Draft" (legacy). pub fn default_project_open_subdir() -> String { - "06-First Draft".to_string() + "05-First Draft".to_string() } /// Templates ship hooks because they are meant to run; honouring them is the @@ -226,6 +227,9 @@ pub fn default_projects_dir() -> PathBuf { /// Default new-file template: the editorial header fields this app already /// understands, followed by the draft marker so the body starts below it. +/// +/// Note: For YAML frontmatter support, create files manually with --- delimiters. +/// The legacy header format is kept for backward compatibility with the parser. pub fn default_new_file_template() -> String { [ "# Title: {{name}}", @@ -521,13 +525,13 @@ mod tests { } /// The folder opened after generating a project. It is the snowflake - /// template's drafting folder, and the name contains a space — which has to - /// survive being stored and joined onto the project path. + /// template's drafting folder (merged planning + draft), and the name contains + /// a space — which has to survive being stored and joined onto the project path. #[test] fn the_default_project_subdir_is_the_drafting_folder() { - assert_eq!(default_project_open_subdir(), "06-First Draft"); + assert_eq!(default_project_open_subdir(), "05-First Draft"); let joined = PathBuf::from("/tmp/The Winter Gate").join(default_project_open_subdir()); - assert_eq!(joined, PathBuf::from("/tmp/The Winter Gate/06-First Draft")); + assert_eq!(joined, PathBuf::from("/tmp/The Winter Gate/05-First Draft")); } /// A config.json written before screenplay projects existed. Same risk as diff --git a/src/preprocess.rs b/src/preprocess.rs index a3e1076..40e0271 100644 --- a/src/preprocess.rs +++ b/src/preprocess.rs @@ -110,6 +110,40 @@ pub fn split_at_marker<'a>(text: &'a str, marker: &str) -> Option<(&'a str, &'a None } +/// Split a document at its YAML frontmatter boundaries (`---` delimiters). +/// Returns `(frontmatter, body)` if frontmatter exists, or `None` if no frontmatter. +/// The frontmatter includes the opening and closing `---` lines. +pub fn split_yaml_frontmatter<'a>(text: &'a str) -> Option<(&'a str, &'a str)> { + let mut lines = text.lines(); + + // Check for opening --- + let first_line = lines.next()?.trim(); + if first_line != "---" { + return None; + } + + // Find closing --- + let mut frontmatter_end = first_line.len() + 1; // +1 for newline + let mut found_closing = false; + + for line in lines { + frontmatter_end += line.len() + 1; // +1 for newline + if line.trim() == "---" { + found_closing = true; + break; + } + } + + if !found_closing { + return None; + } + + // Return frontmatter (including delimiters) and body + let frontmatter = &text[..frontmatter_end]; + let body = &text[frontmatter_end..]; + Some((frontmatter, body)) +} + /// One `#* Name: value` line from a document's editorial header. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Field { diff --git a/src/project_template.rs b/src/project_template.rs index 01ef19e..f6ed124 100644 --- a/src/project_template.rs +++ b/src/project_template.rs @@ -110,6 +110,20 @@ pub fn render_template(config: &RenderConfig) -> RenderResult { .map(|(i, c)| if i == 0 { c.to_uppercase().collect::() } else { c.to_lowercase().collect::() }) .collect::()) // Simplified title case }); + // Capitalize filter - capitalizes the first letter of each word + env.add_filter("capitalize", |value: String| -> Result { + Ok(value.chars() + .enumerate() + .map(|(i, c)| if i == 0 { c.to_uppercase().collect::() } else { c.to_lowercase().collect::() }) + .collect::()) + }); + // capitalizes filter (plural) - same as capitalize but handles the common template usage + env.add_filter("capitalizes", |value: String| -> Result { + Ok(value.chars() + .enumerate() + .map(|(i, c)| if i == 0 { c.to_uppercase().collect::() } else { c.to_lowercase().collect::() }) + .collect::()) + }); // Get the context from variables let context = config.variables.to_context(); diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/03-Story-Bible/CONSISTENCY.md b/templates/snowflake/{{ cookiecutter.project_name }}/03-Story-Bible/CONSISTENCY.md index 0830a8b..161808e 100644 --- a/templates/snowflake/{{ cookiecutter.project_name }}/03-Story-Bible/CONSISTENCY.md +++ b/templates/snowflake/{{ cookiecutter.project_name }}/03-Story-Bible/CONSISTENCY.md @@ -143,8 +143,8 @@ updated: "" ## Quick Verification Commands Use your editor's search: -- `{{ character.name }}` - Find all mentions of a character -- `{{ location.name }}` - Find all mentions of a location +- `{{ '{{' }} character.name {{ '}}' }}` - Find all mentions of a character +- `{{ '{{' }} location.name {{ '}}' }}` - Find all mentions of a location - `[[` - Find all cross-references - `status:` - Find all status fields diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 1/scene01.md b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 1/scene01.md new file mode 100644 index 0000000..bfafc95 --- /dev/null +++ b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 1/scene01.md @@ -0,0 +1,128 @@ +--- +id: scene_01 +title: "Chapter One: The Beginning" +slug: chapter-one-the-beginning +act: 1 +chapter: 1 +scene: 1 +type: chapter +status: draft +word_count_target: 2000 +word_count_min: 1800 +word_count_max: 2200 +pov: "" +characters: [] +setting: "" +date: "" +time: "" +conflict: "" +theme: "" +tone: "" +word_count: 0 +word_count_updated: "" +session_word_count: 0 +last_session: "" +total_sessions: 0 +version: 1 +created: "" +updated: "" +order: 1 +--- + +# Chapter One: The Beginning + +**Scene File** | **ID:** scene_01 | **Status:** Draft + +--- + +## Scene Metadata + +| Attribute | Value | +|-----------|-------| +| **Act** | 1 | +| **Chapter** | 1 | +| **Scene** | 1 | +| **Type** | Chapter | +| **POV** | Not set | +| **Version** | 1 | +| **Word Count Target** | 2000 | + +--- + +## Word Count Tracking + +| Metric | Value | +|--------|-------| +| **Target** | 2000 | +| **Minimum** | 1800 | +| **Maximum** | 2200 | +| **Current** | 0 | +| **This Session** | 0 | +| **Last Updated** | Never | + +--- + +## Creative Elements + +### POV +> Not specified + +### Characters + +### Setting +> Not specified + +### Date & Time +> Not specified | Not specified + +--- + +## Story Structure + +### Conflict +> Not specified + +### Theme +> Not specified + +### Tone +> Not specified + +--- + +## Draft Content + +### Rough Draft: + +[Write your scene content here...] + +--- + +## Writing Notes + +### Session Log +| Date | Words Added | Notes | +|------|--------------|-------| + + +### Revision Notes +- +- + +--- + +## Status Checklist + +- [ ] Planning complete +- [ ] First draft complete +- [ ] Word count target met +- [ ] POV consistent +- [ ] Character voices distinct +- [ ] Setting details accurate +- [ ] Conflict resolved/advanced +- [ ] Ready for revision + +--- + +**Created:** | **Updated:** + diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/act_2/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 2/.gitkeep similarity index 100% rename from templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/act_2/.gitkeep rename to templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 2/.gitkeep diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 2/scene01.md b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 2/scene01.md new file mode 100644 index 0000000..7715eaa --- /dev/null +++ b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 2/scene01.md @@ -0,0 +1,129 @@ +--- +id: scene_02_01 +title: "Chapter Two: Development" +slug: chapter-two-development +act: 2 +chapter: 1 +scene: 1 +type: chapter +status: draft +word_count_target: 2000 +word_count_min: 1800 +word_count_max: 2200 +pov: "" +characters: [] +setting: "" +date: "" +time: "" +conflict: "" +theme: "" +tone: "" +word_count: 0 +word_count_updated: "" +session_word_count: 0 +last_session: "" +total_sessions: 0 +version: 1 +created: "" +updated: "" +planning_template: "" +draft_file: "" +order: 1 +--- + +# Chapter Two: Development + +**Draft File** | **ID:** scene_02_01 | **Status:** Draft + +--- + +## Scene Metadata + +| Attribute | Value | +|-----------|-------| +| **Act** | 2 | +| **Chapter** | 1 | +| **Scene** | 1 | +| **Type** | Chapter | +| **POV** | Not set | +| **Version** | 1 | +| **Word Count Target** | 2000 | + +--- + +## Word Count Tracking + +| Metric | Value | +|--------|-------| +| **Target** | 2000 | +| **Minimum** | 1800 | +| **Maximum** | 2200 | +| **Current** | 0 | +| **This Session** | 0 | +| **Last Updated** | Never | + +--- + +## Creative Elements + +### POV +> Not specified + +### Characters + +### Setting +> Not specified + +### Date & Time +> Not specified | Not specified + +--- + +## Story Structure + +### Conflict +> Not specified + +### Theme +> Not specified + +### Tone +> Not specified + +--- + +## Draft Content + +### Rough Draft: + +[Write your scene content here...] + +--- + +## Writing Notes + +### Session Log +| Date | Words Added | Notes | +|------|--------------|-------| + + +### Revision Notes +- +- + +--- + +## Status Checklist + +- [ ] Planning complete +- [ ] First draft complete +- [ ] Word count target met +- [ ] POV consistent +- [ ] Character voices distinct +- [ ] Setting details accurate +- [ ] Conflict resolved/advanced +- [ ] Ready for revision + +--- + +**Created:** | **Updated:** diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/act_3/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 3/.gitkeep similarity index 100% rename from templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/act_3/.gitkeep rename to templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 3/.gitkeep diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 3/scene01.md b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 3/scene01.md new file mode 100644 index 0000000..4f6e998 --- /dev/null +++ b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Act 3/scene01.md @@ -0,0 +1,129 @@ +--- +id: scene_03_01 +title: "Chapter Three: Climax" +slug: chapter-three-climax +act: 3 +chapter: 1 +scene: 1 +type: chapter +status: draft +word_count_target: 2000 +word_count_min: 1800 +word_count_max: 2200 +pov: "" +characters: [] +setting: "" +date: "" +time: "" +conflict: "" +theme: "" +tone: "" +word_count: 0 +word_count_updated: "" +session_word_count: 0 +last_session: "" +total_sessions: 0 +version: 1 +created: "" +updated: "" +planning_template: "" +draft_file: "" +order: 1 +--- + +# Chapter Three: Climax + +**Draft File** | **ID:** scene_03_01 | **Status:** Draft + +--- + +## Scene Metadata + +| Attribute | Value | +|-----------|-------| +| **Act** | 3 | +| **Chapter** | 1 | +| **Scene** | 1 | +| **Type** | Chapter | +| **POV** | Not set | +| **Version** | 1 | +| **Word Count Target** | 2000 | + +--- + +## Word Count Tracking + +| Metric | Value | +|--------|-------| +| **Target** | 2000 | +| **Minimum** | 1800 | +| **Maximum** | 2200 | +| **Current** | 0 | +| **This Session** | 0 | +| **Last Updated** | Never | + +--- + +## Creative Elements + +### POV +> Not specified + +### Characters + +### Setting +> Not specified + +### Date & Time +> Not specified | Not specified + +--- + +## Story Structure + +### Conflict +> Not specified + +### Theme +> Not specified + +### Tone +> Not specified + +--- + +## Draft Content + +### Rough Draft: + +[Write your scene content here...] + +--- + +## Writing Notes + +### Session Log +| Date | Words Added | Notes | +|------|--------------|-------| + + +### Revision Notes +- +- + +--- + +## Status Checklist + +- [ ] Planning complete +- [ ] First draft complete +- [ ] Word count target met +- [ ] POV consistent +- [ ] Character voices distinct +- [ ] Setting details accurate +- [ ] Conflict resolved/advanced +- [ ] Ready for revision + +--- + +**Created:** | **Updated:** diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Act 2/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Misc Scenes/.gitkeep similarity index 100% rename from templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Act 2/.gitkeep rename to templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/Misc Scenes/.gitkeep diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/_template.md b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/_template.md new file mode 100644 index 0000000..9b336ea --- /dev/null +++ b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/_template.md @@ -0,0 +1,164 @@ +--- +# Merged Planning + Draft Template +# YAML frontmatter contains all planning fields; body is the draft content + +id: scene_new +# Unique identifier for this scene + +title: "New Scene Title" +# Display title for the scene + +slug: new-scene-title +# URL-friendly slug + +# === Core Metadata === +act: 1 +chapter: 1 +scene: 99 +type: scene +# Type: scene, chapter, interlude, etc. + +# === Planning Fields === +status: draft +# Status: planning, draft, revised, done +word_count_target: 2000 +word_count_min: 1800 +word_count_max: 2200 + +# === Creative Elements === +pov: "" +# Point of view character + +characters: [] +# Characters appearing in this scene (array of names) + +setting: "" +# Location/setting +date: "" +time: "" +# Date and time of scene + +conflict: "" +# Central conflict in this scene +theme: "" +# Themes explored +tone: "" +# Mood/tone + +# === Draft Tracking === +word_count: 0 +word_count_updated: "" +session_word_count: 0 +last_session: "" +total_sessions: 0 +version: 1 + +# === Timestamps === +created: "" +updated: "" + +# === Linking === +# These are kept for backward compatibility but are no longer needed +# since planning and draft are merged +planning_template: "" +draft_file: "" +order: 99 +--- + +# New Scene Title + +**Scene File** | **ID:** scene_new | **Status:** Draft + +--- + +## Scene Metadata + +| Attribute | Value | +|-----------|-------| +| **Act** | 1 | +| **Chapter** | 1 | +| **Scene** | 99 | +| **Type** | Scene | +| **POV** | Not set | +| **Version** | 1 | +| **Word Count Target** | 2000 | + +--- + +## Word Count Tracking + +| Metric | Value | +|--------|-------| +| **Target** | 2000 | +| **Minimum** | 1800 | +| **Maximum** | 2200 | +| **Current** | 0 | +| **This Session** | 0 | +| **Last Updated** | Never | + +--- + +## Creative Elements + +### POV +> Not specified + +### Characters + +### Setting +> Not specified + +### Date & Time +> Not specified | Not specified + +--- + +## Story Structure + +### Conflict +> Not specified + +### Theme +> Not specified + +### Tone +> Not specified + +--- + +## Draft Content + +### Rough Draft: + +[Write your scene content here...] + +--- + +## Writing Notes + +### Session Log +| Date | Words Added | Notes | +|------|--------------|-------| + + +### Revision Notes +- +- + +--- + +## Status Checklist + +- [ ] Planning complete +- [ ] First draft complete +- [ ] Word count target met +- [ ] POV consistent +- [ ] Character voices distinct +- [ ] Setting details accurate +- [ ] Conflict resolved/advanced +- [ ] Ready for revision + +--- + +**Created:** | **Updated:** + diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/draft_v1.md b/templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/draft_v1.md similarity index 100% rename from templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/draft_v1.md rename to templates/snowflake/{{ cookiecutter.project_name }}/05-First Draft/draft_v1.md diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/_template.md b/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/_template.md deleted file mode 100644 index 676f662..0000000 --- a/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/_template.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -id: scene_new -title: "New Scene Title" -slug: new-scene-title -act: 1 -chapter: 1 -scene: 99 -type: scene -status: planning -word_count_target: 2000 -word_count_min: 1800 -word_count_max: 2200 -pov: "" -characters: [] -setting: "" -date: "" -time: "" -conflict: "" -theme: "" -tone: "" -draft_file: "" -order: 99 -created: "" -updated: "" ---- - -# New Scene Title - -**Planning Template** | **ID:** scene_new | **Status:** {{ status | capitalizes }} - ---- - -## Planning Metadata - -| Attribute | Value | -|-----------|-------| -| **Act** | {{ act }} | -| **Chapter** | {{ chapter }} | -| **Scene** | {{ scene }} | -| **Type** | {{ type | capitalizes }} | -| **Order** | {{ order }} | -| **Draft File** | {{ draft_file if draft_file else "[Create Draft File](#)" }} | - ---- - -## Creative Elements - -### POV -> {{ pov if pov else "Not specified" }} - -### Characters -{% for character in characters %}- [[{{ character }}]] -{% endfor %} - -### Setting -> {{ setting if setting else "Not specified" }} - -### Date & Time -> {{ date if date else "Not specified" }} | {{ time if time else "Not specified" }} - ---- - -## Story Structure - -### Conflict -> {{ conflict if conflict else "Not specified" }} - -### Theme -> {{ theme if theme else "Not specified" }} - -### Tone -> {{ tone if tone else "Not specified" }} - ---- - -## Word Count Goals - -| Metric | Value | -|--------|-------| -| **Target** | {{ word_count_target }} | -| **Minimum** | {{ word_count_min }} | -| **Maximum** | {{ word_count_max }} | - ---- - -## Scene Planning - -### The Setup -> - -### The Reveal -> - -### Things to Note -- -- - ---- - -## Status Tracking - -- [ ] Scene outline complete -- [ ] Character arcs aligned -- [ ] Location details verified -- [ ] Conflict established -- [ ] Word count target set -- [ ] Ready for drafting - ---- - -**Instructions:** -1. Copy this file to the appropriate act/chapter folder -2. Rename to `scene_XX.md` (e.g., `scene_02.md`) -3. Update the YAML frontmatter with scene details -4. Set `draft_file` to point to the corresponding draft file -5. Create the draft file using the template in `06-First Draft/_template.md` - -**Related:** [Story Bible](../../03-Story-Bible/_index.md) | **Created:** {{ created }} | **Updated:** {{ updated }} diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/act_1/scene_01.md b/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/act_1/scene_01.md deleted file mode 100644 index f08af24..0000000 --- a/templates/snowflake/{{ cookiecutter.project_name }}/05-Plot/act_1/scene_01.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -id: scene_01 -title: "Chapter One: The Beginning" -slug: chapter-one-the-beginning -act: 1 -chapter: 1 -scene: 1 -type: chapter -status: planning -word_count_target: 2000 -word_count_min: 1800 -word_count_max: 2200 -pov: "" -characters: [] -setting: "" -date: "" -time: "" -conflict: "" -theme: "" -tone: "" -draft_file: "../../06-First Draft/Act 1/scene01.md" -order: 1 -created: "" -updated: "" ---- - -# Chapter One: The Beginning - -**Planning Template** | **ID:** scene_01 | **Status:** {{ status | capitalizes }} - ---- - -## Planning Metadata - -| Attribute | Value | -|-----------|-------| -| **Act** | {{ act }} | -| **Chapter** | {{ chapter }} | -| **Scene** | {{ scene }} | -| **Type** | {{ type | capitalizes }} | -| **Order** | {{ order }} | -| **Draft File** | [`{{ draft_file | replace('../../', '') }}`]({{ draft_file }}) | - ---- - -## Creative Elements - -### POV -> {{ pov if pov else "Not specified" }} - -### Characters -{% for character in characters %}- [[{{ character }}]] -{% endfor %} - -### Setting -> {{ setting if setting else "Not specified" }} - -### Date & Time -> {{ date if date else "Not specified" }} | {{ time if time else "Not specified" }} - ---- - -## Story Structure - -### Conflict -> {{ conflict if conflict else "Not specified" }} - -### Theme -> {{ theme if theme else "Not specified" }} - -### Tone -> {{ tone if tone else "Not specified" }} - ---- - -## Word Count Goals - -| Metric | Value | -|--------|-------| -| **Target** | {{ word_count_target }} | -| **Minimum** | {{ word_count_min }} | -| **Maximum** | {{ word_count_max }} | - ---- - -## Scene Planning - -### The Setup -> - -### The Reveal -> - -### Things to Note -- -- - ---- - -## Status Tracking - -- [ ] Scene outline complete -- [ ] Character arcs aligned -- [ ] Location details verified -- [ ] Conflict established -- [ ] Word count target set -- [ ] Ready for drafting - ---- - -**Draft File:** [Open Draft]({{ draft_file }}) | **Created:** {{ created }} | **Updated:** {{ updated }} \ No newline at end of file diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Act 1/scene01.md b/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Act 1/scene01.md deleted file mode 100644 index 3fa9085..0000000 --- a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Act 1/scene01.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -id: draft_scene_01 -title: "Chapter One: The Beginning" -slug: chapter-one-the-beginning -planning_template: "../../05-Plot/act_1/scene_01.md" -act: 1 -chapter: 1 -scene: 1 -type: draft -status: not_started -word_count: 0 -word_count_updated: "" -session_word_count: 0 -last_session: "" -total_sessions: 0 -pov: "" -version: 1 -created: "" -updated: "" ---- - -# Chapter One: The Beginning - -**Draft File** | **ID:** draft_scene_01 | **Status:** {{ status | replace('_', ' ') | capitalizes }} - ---- - -## Planning Reference - -> **Linked to:** [Planning Template]({{ planning_template }}) - ---- - -## Scene Metadata - -| Attribute | Value | -|-----------|-------| -| **Act** | {{ act }} | -| **Chapter** | {{ chapter }} | -| **Scene** | {{ scene }} | -| **Type** | {{ type | capitalizes }} | -| **POV** | {{ pov if pov else "Not set" }} | -| **Version** | {{ version }} | - ---- - -## Word Count Tracking - -| Metric | Value | -|--------|-------| -| **Target** | 2000 (from planning) | -| **Current** | {{ word_count }} | -| **This Session** | {{ session_word_count }} | -| **Last Updated** | {{ word_count_updated if word_count_updated else "Never" }} | - ---- - -## Draft Content - -### Rough Draft: - -[Write your scene content here...] - ---- - -## Writing Notes - -### Session Log -| Date | Words Added | Notes | -|------|--------------|-------| -| {{ last_session if last_session else "" }} | {{ session_word_count }} | | - -### Revision Notes -- -- - ---- - -## Status Checklist - -- [ ] First draft complete -- [ ] Word count target met -- [ ] POV consistent -- [ ] Character voices distinct -- [ ] Setting details accurate -- [ ] Conflict resolved/advanced -- [ ] Ready for revision - ---- - -**Planning Template:** [Open Planning]({{ planning_template }}) | **Created:** {{ created }} | **Updated:** {{ updated }} diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Act 3/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Act 3/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Misc Scenes/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/Misc Scenes/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/_template.md b/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/_template.md deleted file mode 100644 index 97e6881..0000000 --- a/templates/snowflake/{{ cookiecutter.project_name }}/06-First Draft/_template.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -id: draft_scene_new -title: "New Scene Title" -slug: new-scene-title -planning_template: "" -act: 1 -chapter: 1 -scene: 99 -type: draft -status: not_started -word_count: 0 -word_count_updated: "" -session_word_count: 0 -last_session: "" -total_sessions: 0 -pov: "" -version: 1 -created: "" -updated: "" ---- - -# New Scene Title - -**Draft File** | **ID:** draft_scene_new | **Status:** {{ status | replace('_', ' ') | capitalizes }} - ---- - -## Planning Reference - -> **Linked to:** {{ planning_template if planning_template else "[Create Planning Template](#)" }} - ---- - -## Scene Metadata - -| Attribute | Value | -|-----------|-------| -| **Act** | {{ act }} | -| **Chapter** | {{ chapter }} | -| **Scene** | {{ scene }} | -| **Type** | {{ type | capitalizes }} | -| **POV** | {{ pov if pov else "Not set" }} | -| **Version** | {{ version }} | - ---- - -## Word Count Tracking - -| Metric | Value | -|--------|-------| -| **Target** | (from planning) | -| **Current** | {{ word_count }} | -| **This Session** | {{ session_word_count }} | -| **Last Updated** | {{ word_count_updated if word_count_updated else "Never" }} | - ---- - -## Draft Content - -### Rough Draft: - -[Write your scene content here...] - ---- - -## Writing Notes - -### Session Log -| Date | Words Added | Notes | -|------|--------------|-------| -| {{ last_session if last_session else "" }} | {{ session_word_count }} | | - -### Revision Notes -- -- - ---- - -## Status Checklist - -- [ ] First draft complete -- [ ] Word count target met -- [ ] POV consistent -- [ ] Character voices distinct -- [ ] Setting details accurate -- [ ] Conflict resolved/advanced -- [ ] Ready for revision - ---- - -**Instructions:** -1. Copy this file to the appropriate Act/Chapter folder -2. Rename to `sceneXX.md` (e.g., `scene02.md`) -3. Update the YAML frontmatter with scene details -4. Set `planning_template` to point to the corresponding planning file -5. Create the planning file using the template in `05-Plot/_template.md` -6. Update word count as you write - -**Related:** [Story Bible](../../03-Story-Bible/_index.md) | **Created:** {{ created }} | **Updated:** {{ updated }}