@model ProjectIndexViewModel @{ ViewData["Title"] = "Projects"; var trial = Model.Trial; }

Series planning

Projects

Import JSON New project
@if (trial is not null) {

Free trial status

@trial.StatusLabel on @trial.PlanName

Your 30-day trial expires on @FormatDate(trial.ExpiryDateUtc). Upgrade whenever you are ready.

Upgrade
} @if (Model.OnboardingNudge.ShouldShow && !Model.StoryIntelligence.ShouldShow) {

First setup

@Model.OnboardingNudge.Title

@Model.OnboardingNudge.Description

@Model.OnboardingNudge.ButtonText
} @if (Model.StoryIntelligence.ShouldShow) {

Manuscript import

@Model.StoryIntelligence.Title

@Model.StoryIntelligence.Description

@Model.StoryIntelligence.ButtonText
} @if (TempData["ArchiveMessage"] is string archiveMessage) {
@archiveMessage
} @if (TempData["ArchiveError"] is string archiveError) {
@archiveError
} @if (TempData["ProjectExportMessage"] is string projectExportMessage) {
@projectExportMessage
} @if (!Model.ActiveProjects.Any() && !Model.ArchivedProjects.Any()) {

Start with a series or standalone novel

Create a project, then add books, chapters and scenes in narrative order.

Create your first project
} else { } @functions { private static string FormatDate(DateTime value) => value.ToLocalTime().ToString("yyyy-MM-dd"); private static DateTime ProjectLastUpdated(ProjectIndexCardViewModel project) => new[] { project.UpdatedDate, project.LastBookUpdatedDate ?? project.UpdatedDate }.Max(); private static string Initials(string value) { var words = value .Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Take(2) .Select(word => char.ToUpperInvariant(word[0])); var initials = string.Concat(words); return string.IsNullOrWhiteSpace(initials) ? "PD" : initials; } } @section Scripts { }