@model StoryBibleViewModel @{ ViewData["Title"] = $"Story Bible - {Model.Project.ProjectName}"; var timelineByBook = Model.Timeline.GroupBy(x => new { x.BookID, x.BookTitle }); var relationshipsByCharacter = Model.Relationships.GroupBy(x => new { x.CharacterAID, x.CharacterAName }); var revisionByGroup = Model.RevisionItems.GroupBy(x => x.GroupName); }
Project workspace @Model.Project.ProjectName

Reference

Story Bible

A project-level reference for people, threads, places, assets, continuity, and revision attention.

Printable Story Bible Markdown Text Timeline export Research pack Open Relationship Map
@if (!string.IsNullOrWhiteSpace(Model.Query)) {

Search

Results for "@Model.Query"

Clear search Export results
@if (!Model.SearchResults.Any()) {

No matching story bible entries. Try a character name, location, asset, plot thread, or scene title.

} else {
@foreach (var group in Model.SearchResults.GroupBy(x => x.ResultType)) {

@group.Key

    @foreach (var result in group) {
  • @result.Title @if (!string.IsNullOrWhiteSpace(result.Detail)) { @result.Detail }
  • }
}
}
}

People

Characters

@Model.Characters.Count characters
@foreach (var character in Model.Characters) {

@character.CharacterName

@character.SceneCount scenes

@(character.Description ?? "No profile description yet.")

@if (character.AgeAtSeriesStart.HasValue) { Age @character.AgeAtSeriesStart } @if (!string.IsNullOrWhiteSpace(character.EyeColour)) { @character.EyeColour eyes } @if (!string.IsNullOrWhiteSpace(character.Height)) { @character.Height } @character.PovSceneCount POV scenes @character.RelationshipCount relationships @character.KnowledgeCount knowledge notes
First
@(character.FirstSceneLabel ?? "Not placed")
Last
@(character.LastSceneLabel ?? "Not placed")
Locations
@(character.LocationHistory ?? "No location history yet")
@if (character.MissingLocationCount > 0) { @character.MissingLocationCount missing locations }
Open profile Show on timeline
}

Questions and promises

Plot Threads

@Model.PlotThreads.Count threads
@foreach (var thread in Model.PlotThreads) {

@thread.ThreadTitle

@thread.ThreadStatusName
@thread.PlotLineName @thread.ThreadTypeName Importance @thread.Importance @thread.EventCount events
Introduced
@(thread.IntroducedSceneLabel ?? "Not set")
Last touched
@(thread.LastTouchedSceneLabel ?? "No events yet")
Planned end
@(thread.PlannedResolutionSceneLabel ?? "Not planned")
Actual end
@(thread.ActualResolutionSceneLabel ?? "Not resolved")
History
@(thread.EventHistory ?? "No event history yet")
@if (thread.WarningCount > 0) { @thread.WarningCount warnings }
Edit thread Show on timeline
}

Objects and evidence

Story Assets

@Model.Assets.Count assets
@foreach (var asset in Model.Assets) {

@asset.AssetName

@(asset.IsResolved ? "Resolved" : "Open")
@asset.KindName @(asset.CurrentStateName ?? "No state") Importance @asset.Importance @asset.EventCount events
Location
@(asset.CurrentLocationPath ?? "No current location")
Dependencies
@(asset.DependencySummary ?? "None")
Custody
@(asset.CustodySummary ?? "No custody history")
History
@(asset.EventHistory ?? "No event history yet")
@if (asset.WarningCount > 0) { @asset.WarningCount warnings }
Open asset Show on timeline
}

Character web

Relationships

@Model.Relationships.Count relationships
@foreach (var categoryGroup in Model.Relationships.GroupBy(x => new { x.RelationshipCategoryName, x.CategorySortOrder }).OrderBy(x => x.Key.CategorySortOrder).ThenBy(x => x.Key.RelationshipCategoryName)) {

@categoryGroup.Key.RelationshipCategoryName

    @foreach (var relationship in categoryGroup.OrderBy(x => x.CharacterAName).ThenBy(x => x.CharacterBName).ThenBy(x => x.RelationshipTypeSortOrder)) {
  • @relationship.CharacterAName / @relationship.CharacterBName @relationship.RelationshipTypeName @relationship.RelationshipCategoryName Initial: @(relationship.InitialRelationshipName ?? relationship.RelationshipTypeName)@if (!string.IsNullOrWhiteSpace(relationship.InitialStateName)) { / @relationship.InitialStateName }@if (relationship.InitialIntensity.HasValue) { / Intensity @relationship.InitialIntensity } Current: @(relationship.CurrentStateName ?? "No current state")@if (relationship.CurrentIntensity.HasValue) { / Intensity @relationship.CurrentIntensity } @if (!string.IsNullOrWhiteSpace(relationship.EventHistory)) { Relationship Event History: @relationship.EventHistory }
  • }
}

Place

Locations

@Model.Locations.Count locations
@foreach (var location in Model.Locations) {

@location.LocationName

@(location.LocationTypeName ?? "Location")

@location.LocationPath

@location.SceneCount scenes @location.CharacterCount characters @location.AssetCount assets @location.RelationshipCount links
@if (!string.IsNullOrWhiteSpace(location.RelatedLocations)) {

Linked to @location.RelatedLocations

}
Open location Show on timeline
}

Narrative order

Timeline Summary

Open timeline
@foreach (var book in timelineByBook) {

@book.Key.BookTitle

@foreach (var chapter in book.GroupBy(x => new { x.ChapterID, x.ChapterNumber, x.ChapterTitle })) {

Chapter @chapter.Key.ChapterNumber: @chapter.Key.ChapterTitle

@foreach (var scene in chapter) {
Scene @scene.SceneNumber: @scene.SceneTitle @scene.RevisionStatusName POV: @(scene.PovCharacterName ?? "Not set") Location: @(scene.LocationPath ?? "Not set") @if (!string.IsNullOrWhiteSpace(scene.Summary)) {

@scene.Summary

}
}
}
}

Open Questions

Things that may need attention

@Model.OpenQuestions.Count items
@foreach (var item in Model.OpenQuestions) {
@item.Category @item.Title @if (!string.IsNullOrWhiteSpace(item.Detail)) {

@item.Detail

} @if (item.SceneID.HasValue) { Open scene }
}

Revision

Revision Status

@foreach (var group in revisionByGroup) {

@group.Key

@group.Sum(x => x.ItemCount)
    @foreach (var item in group) {
  • @(item.Detail ?? item.GroupName) @item.ItemCount
  • }
}
@functions { private string StoryBibleLink(StoryBibleSearchResult result, int projectId) { return result.ResultType switch { "Scene" => Url.Action("Index", "Timeline", new { projectId, selectedSceneId = result.SceneID ?? result.EntityID }) ?? "#", "Character" => Url.Action("Details", "Characters", new { id = result.EntityID }) ?? "#", "Story Asset" => Url.Action("Details", "StoryAssets", new { id = result.EntityID }) ?? "#", "Plot Thread" => Url.Action("Edit", "PlotThreads", new { id = result.EntityID }) ?? "#", "Location" => Url.Action("Details", "Locations", new { id = result.EntityID }) ?? "#", "Warning" => Url.Action("Index", "Warnings", new { projectId, sceneId = result.SceneID }) ?? "#", _ => Url.Action("Index", "StoryBible", new { projectId }) ?? "#" }; } }