Compare commits
3 Commits
6afa0cdf0d
...
3e258930a8
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e258930a8 | |||
| 0fded0b845 | |||
| ca5c8862fd |
@@ -233,3 +233,73 @@ input:focus, textarea:focus {
|
|||||||
height: 1px;
|
height: 1px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Course landing pages (layouts/courses/single.html) */
|
||||||
|
.course-hero {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.course-subhead {
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--fg-muted);
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.course-value-prop {
|
||||||
|
font-size: 1.05rem;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
.course-social-proof {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--fg-muted);
|
||||||
|
}
|
||||||
|
.enroll-form {
|
||||||
|
max-width: 24rem;
|
||||||
|
margin: 1.5rem auto;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.enroll-status {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-credibility,
|
||||||
|
.course-curriculum {
|
||||||
|
background: var(--bg-raised);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 2rem;
|
||||||
|
margin: 3rem 0;
|
||||||
|
}
|
||||||
|
.course-bullets {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 1.5rem 0 0;
|
||||||
|
}
|
||||||
|
.course-bullets li {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 1.75rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
.course-bullets li::before {
|
||||||
|
content: "✓";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: var(--cta);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.course-curriculum-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 1.5rem 0 0;
|
||||||
|
}
|
||||||
|
.course-curriculum-list li {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.course-day-label {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
color: var(--cta);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.course-repeat-cta {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,39 @@
|
|||||||
---
|
---
|
||||||
title: "Find Your Right Readers"
|
title: "The Find Your Right Readers Roadmap"
|
||||||
description: "A free email course for fiction authors on finding the readers who were always meant to find their story."
|
description: "How to find readers who actually need your stories? avoid these 5 mistakes that lead to 0 sales on launch day, writing for an audience of 1 (just your mom), and posting every day for a year with nothing to show for it (even if you have zero platform and hate marketing)"
|
||||||
eec_slug: "find-your-right-readers"
|
eec_slug: "find-your-right-readers"
|
||||||
pitch: |
|
|
||||||
Most advice about "finding readers" is really just advice about marketing —
|
# Optional italic line under the title, for handling an objection up front.
|
||||||
ads, algorithms, funnels. This is different. Over a few short emails, at
|
hero_subhead: "How to find readers who actually need your stories? avoid these 5 mistakes that lead to 0 sales on launch day, writing for an audience of 1 (just your mom), and posting every day for a year with nothing to show for it (even if you have zero platform and hate marketing)"
|
||||||
whatever pace you want to take it, I'll walk through how to think about who
|
|
||||||
your right readers actually are, and how to build a real path to them
|
# Optional line under the signup button.
|
||||||
instead of shouting into the void.
|
# social_proof: "Join a few hundred authors who've already started."
|
||||||
|
|
||||||
|
# Optional label on every "Send me day one" button across the page.
|
||||||
|
cta_text: "Get me started!"
|
||||||
|
|
||||||
|
# Optional "who's teaching this and why" section. Both fields are independently
|
||||||
|
# optional — set either or both.
|
||||||
|
credibility_heading: "Written by Will Estes, who's..."
|
||||||
|
credibility_bullets:
|
||||||
|
- "Noticed that most advice on selling your book is marketing advice about hustling."
|
||||||
|
- "Believes that most writers want to think about stories, not their next ad campaign."
|
||||||
|
|
||||||
|
# Optional day-by-day curriculum preview. `label` is optional per item.
|
||||||
|
curriculum_heading: "Here's what's inside"
|
||||||
|
curriculum_intro: "Five short emails, sent at whatever pace you want."
|
||||||
|
curriculum_items:
|
||||||
|
- label: "Day 1."
|
||||||
|
text: "Mistake #1: Writing for everyone who reads books. (Why a smaller target means more hits.)"
|
||||||
|
- label: "Day 2."
|
||||||
|
text: "Mistake #2: Perfecting your book before you start building your audience"
|
||||||
|
- label: "Day 3."
|
||||||
|
text: "Mistake #3: Selling the plot instead of the feeling."
|
||||||
|
- label: "Day 4."
|
||||||
|
text: "Mistake #4: Looking for readers in the wrong places. (Finding the people who need your stories means not talking to the ones who don't.)"
|
||||||
|
- label: "Day 5."
|
||||||
|
text: "Mistake #5: Quitting before the compounding kicks in."
|
||||||
|
|
||||||
|
# Optional heading above the repeated signup form at the bottom of the page.
|
||||||
|
repeat_cta_heading: "Ready to find your right readers?"
|
||||||
---
|
---
|
||||||
|
|||||||
+38
-48
@@ -1,52 +1,42 @@
|
|||||||
{{ define "main" }}
|
{{ define "main" }}
|
||||||
<h1 style="font-size:2rem; margin-bottom:0.5rem;">{{ .Title }}</h1>
|
<section class="course-hero">
|
||||||
{{ with .Params.pitch }}<div style="font-size:1.05rem; opacity:0.9;">{{ . | markdownify }}</div>{{ end }}
|
<h1>{{ .Title }}</h1>
|
||||||
|
{{ with .Params.hero_subhead }}<p class="course-subhead">{{ . }}</p>{{ end }}
|
||||||
|
|
||||||
|
{{ partial "course-enroll-form.html" (dict "id" "top" "page" .) }}
|
||||||
|
|
||||||
|
{{ with .Params.social_proof }}<p class="course-social-proof">{{ . }}</p>{{ end }}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{{ if or .Params.credibility_heading .Params.credibility_bullets }}
|
||||||
|
<section class="course-credibility">
|
||||||
|
{{ with .Params.credibility_heading }}<h2>{{ . }}</h2>{{ end }}
|
||||||
|
{{ with .Params.credibility_bullets }}
|
||||||
|
<ul class="course-bullets">
|
||||||
|
{{ range . }}<li>{{ . | markdownify }}</li>{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
</section>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or .Params.curriculum_heading .Params.curriculum_items }}
|
||||||
|
<section class="course-curriculum">
|
||||||
|
{{ with .Params.curriculum_heading }}<h2>{{ . }}</h2>{{ end }}
|
||||||
|
{{ with .Params.curriculum_intro }}<p>{{ . }}</p>{{ end }}
|
||||||
|
{{ with .Params.curriculum_items }}
|
||||||
|
<ol class="course-curriculum-list">
|
||||||
|
{{ range . }}
|
||||||
|
<li>{{ with .label }}<span class="course-day-label">{{ . }}</span> {{ end }}{{ .text | markdownify }}</li>
|
||||||
|
{{ end }}
|
||||||
|
</ol>
|
||||||
|
{{ end }}
|
||||||
|
</section>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{ .Content }}
|
{{ .Content }}
|
||||||
|
|
||||||
<form id="enroll-form" style="margin-top:2rem; max-width:24rem;">
|
<section class="course-repeat-cta">
|
||||||
<label for="email">Email</label>
|
{{ with .Params.repeat_cta_heading }}<h2>{{ . }}</h2>{{ end }}
|
||||||
<input type="email" id="email" name="email" required autocomplete="email" placeholder="you@example.com">
|
{{ partial "course-enroll-form.html" (dict "id" "bottom" "page" .) }}
|
||||||
|
</section>
|
||||||
<div class="field-honeypot" aria-hidden="true">
|
|
||||||
<label for="website">Leave this field empty</label>
|
|
||||||
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn">Send me day one</button>
|
|
||||||
</form>
|
|
||||||
<p id="enroll-status" role="status" style="margin-top:1rem;"></p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var form = document.getElementById("enroll-form");
|
|
||||||
var status = document.getElementById("enroll-status");
|
|
||||||
var slug = {{ .Params.eec_slug }};
|
|
||||||
form.addEventListener("submit", function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (form.website.value) return; // honeypot
|
|
||||||
var submitBtn = form.querySelector("button[type=submit]");
|
|
||||||
submitBtn.disabled = true;
|
|
||||||
status.textContent = "Signing you up…";
|
|
||||||
fetch("{{ .Site.Params.eec_base_url }}/courses/" + slug + "/enroll", {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({ email: form.email.value })
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.ok) {
|
|
||||||
form.reset();
|
|
||||||
form.hidden = true;
|
|
||||||
status.textContent = "Check your inbox — let us know you're ready and we'll get started.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return res.text().then(function (msg) {
|
|
||||||
submitBtn.disabled = false;
|
|
||||||
status.textContent = msg || "Something went wrong. Try again in a moment.";
|
|
||||||
});
|
|
||||||
}).catch(function () {
|
|
||||||
submitBtn.disabled = false;
|
|
||||||
status.textContent = "Something went wrong. Try again in a moment.";
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{{ $id := .id }}
|
||||||
|
{{ $page := .page }}
|
||||||
|
<form id="enroll-form-{{ $id }}" class="enroll-form">
|
||||||
|
<label for="email-{{ $id }}">Email</label>
|
||||||
|
<input type="email" id="email-{{ $id }}" name="email" required autocomplete="email" placeholder="you@example.com">
|
||||||
|
|
||||||
|
<div class="field-honeypot" aria-hidden="true">
|
||||||
|
<label for="website-{{ $id }}">Leave this field empty</label>
|
||||||
|
<input type="text" id="website-{{ $id }}" name="website" tabindex="-1" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn">{{ $page.Params.cta_text | default "Send me day one" }}</button>
|
||||||
|
</form>
|
||||||
|
<p id="enroll-status-{{ $id }}" role="status" class="enroll-status"></p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var form = document.getElementById("enroll-form-{{ $id }}");
|
||||||
|
var status = document.getElementById("enroll-status-{{ $id }}");
|
||||||
|
var slug = {{ $page.Params.eec_slug }};
|
||||||
|
form.addEventListener("submit", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (form.website.value) return; // honeypot
|
||||||
|
var submitBtn = form.querySelector("button[type=submit]");
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
status.textContent = "Signing you up…";
|
||||||
|
fetch("{{ $page.Site.Params.eec_base_url }}/courses/" + slug + "/enroll", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ email: form.email.value })
|
||||||
|
}).then(function (res) {
|
||||||
|
if (res.ok) {
|
||||||
|
form.reset();
|
||||||
|
form.hidden = true;
|
||||||
|
status.textContent = "Check your inbox — let us know you're ready and we'll get started.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return res.text().then(function (msg) {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
status.textContent = msg || "Something went wrong. Try again in a moment.";
|
||||||
|
});
|
||||||
|
}).catch(function () {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
status.textContent = "Something went wrong. Try again in a moment.";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user