diff --git a/README.md b/README.md
index 97042f6..fb51795 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,8 @@
**Ready-made cinematic scroll websites — no code, pure HTML.**
Pick a template, change the words, and export a production‑ready HTML/CSS/JS ZIP you can
-deploy anywhere. Every template is free on every plan.
+deploy anywhere. The editor, publishing and ZIP export are free, along with 13 of the 21
+templates. The other 8 are bought once, outright.
[Live demo](https://scrollcraft-gilt.vercel.app) · [Report a bug](https://github.com/singhharsh1708/scrollcraft/issues) · [Request a feature](https://github.com/singhharsh1708/scrollcraft/issues)
@@ -250,10 +251,10 @@ coding standards, and how to pick up an issue.
## Sponsor
ScrollCraft is free and open source, and the hosted version costs real money to run
-(model calls, frame rendering, storage). If it saved you a studio invoice, you can
+(frame rendering, blob storage, a database). If it saved you a studio invoice, you can
[sponsor the project on GitHub](https://github.com/sponsors/singhharsh1708), one-off or
-monthly. Sponsoring is separate from the paid plans: it funds the open source work, not an
-account upgrade.
+monthly. Sponsoring funds the open source work — it is not a purchase and unlocks
+nothing, which is deliberate.
Not in a position to pay? Starring the repo, filing a good bug report, or shipping a PR
helps just as much.
diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx
index ab88895..573649b 100644
--- a/src/app/about/page.tsx
+++ b/src/app/about/page.tsx
@@ -6,6 +6,7 @@ import { Badge } from "@/components/ui/badge";
import { ArrowRight, Sparkles, Zap, Globe, Users } from "lucide-react";
import Navbar from "@/components/Navbar";
import { PRESETS } from "@/lib/presets";
+import SiteFooter from "@/components/SiteFooter";
const TEAM = [
{ name: "Harsh Singh", role: "Founder & Engineer", avatar: "HS", bio: "Building the future of no-code web experiences." },
@@ -128,14 +129,7 @@ export default function AboutPage() {
-
+
);
}
diff --git a/src/app/changelog/page.tsx b/src/app/changelog/page.tsx
index 208f439..9399c21 100644
--- a/src/app/changelog/page.tsx
+++ b/src/app/changelog/page.tsx
@@ -1,6 +1,7 @@
import { Badge } from "@/components/ui/badge";
-import { Sparkles } from "lucide-react";
+import { } from "lucide-react";
import Navbar from "@/components/Navbar";
+import SiteFooter from "@/components/SiteFooter";
const ENTRIES = [
{
@@ -131,14 +132,7 @@ export default function ChangelogPage() {
-
+
);
}
diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx
index 1bdbb43..48b343c 100644
--- a/src/app/contact/page.tsx
+++ b/src/app/contact/page.tsx
@@ -4,9 +4,10 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
-import { Sparkles, Mail, MessageSquare, Zap, CheckCircle2 } from "lucide-react";
+import { Mail, MessageSquare, Zap, CheckCircle2 } from "lucide-react";
import { toast } from "sonner";
import Navbar from "@/components/Navbar";
+import SiteFooter from "@/components/SiteFooter";
const TOPICS = ["General question", "Bug report", "Feature request", "Enterprise inquiry", "Billing", "Partnership"];
@@ -118,14 +119,7 @@ export default function ContactPage() {
-
+
);
}
diff --git a/src/app/cookies/page.tsx b/src/app/cookies/page.tsx
index 42ddb8c..ece2641 100644
--- a/src/app/cookies/page.tsx
+++ b/src/app/cookies/page.tsx
@@ -1,5 +1,6 @@
import Link from "next/link";
import Navbar from "@/components/Navbar";
+import SiteFooter from "@/components/SiteFooter";
export const metadata = { title: "Cookie Policy" };
@@ -51,6 +52,7 @@ export default function CookiesPage() {
+
);
}
diff --git a/src/app/templates/[slug]/page.tsx b/src/app/templates/[slug]/page.tsx
index af0064e..ef8c913 100644
--- a/src/app/templates/[slug]/page.tsx
+++ b/src/app/templates/[slug]/page.tsx
@@ -1,5 +1,5 @@
"use client";
-import { use, useCallback, useEffect, useState } from "react";
+import { use, useCallback, useEffect, useMemo, useState } from "react";
import { notFound } from "next/navigation";
import Link from "next/link";
import { Button } from "@/components/ui/button";
@@ -39,12 +39,21 @@ function Preview({
sections: Section[];
children: React.ReactNode;
}) {
+ // SiteRenderer regenerates its frames whenever `styleSpec` changes identity, so this
+ // has to be a stable object. Passing a fresh literal restarted generation on every
+ // re-render, which left the premium preview stuck on "Rendering frames…" forever once
+ // the ownership check gave the component something to re-render for.
+ const styleSpec = useMemo(
+ () => ({ style: template.style, colors: template.colors }),
+ [template.style, template.colors]
+ );
+
return (
@@ -158,8 +167,9 @@ function PremiumPreview({ template }: { template: Template }) {
You're seeing the opening section
- {hidden} more {hidden === 1 ? "section is" : "sections are"} written and waiting.
- Unlock once and it's yours to edit and export forever.
+ {hidden} more {hidden === 1 ? "section is" : "sections are"}{" "}
+ written and waiting. Unlock once and it's yours to edit and export
+ forever.