← back to Dw Marketing Reels
Add public /privacy + /terms pages (no-auth) for Meta app publish requirement
390b976ced7976b4e3f060883a9c36770d0527c6 · 2026-07-14 09:14:44 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Files touched
A public/privacy.htmlA public/terms.htmlM server.js
Diff
commit 390b976ced7976b4e3f060883a9c36770d0527c6
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 14 09:14:44 2026 -0700
Add public /privacy + /terms pages (no-auth) for Meta app publish requirement
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
public/privacy.html | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++
public/terms.html | 86 +++++++++++++++++++++++++++++++++++++++++++++++
server.js | 6 +++-
3 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/public/privacy.html b/public/privacy.html
new file mode 100644
index 0000000..05d9bed
--- /dev/null
+++ b/public/privacy.html
@@ -0,0 +1,96 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Privacy Policy — Designer Wallcoverings</title>
+<style>
+ :root { --ink:#1a1a1a; --muted:#666; --line:#e5e2dc; --bg:#faf8f4; }
+ * { box-sizing:border-box; }
+ body { margin:0; background:var(--bg); color:var(--ink);
+ font:16px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif; }
+ .wrap { max-width:760px; margin:0 auto; padding:56px 24px 96px; }
+ .brand { font-weight:600; letter-spacing:.18em; text-transform:uppercase; font-size:13px; color:var(--muted); }
+ h1 { font-weight:600; font-size:32px; margin:.35em 0 .15em; letter-spacing:-.01em; }
+ .eff { color:var(--muted); font-size:14px; margin-bottom:2em; }
+ h2 { font-size:18px; margin:2em 0 .4em; }
+ p, li { color:#2a2a2a; }
+ a { color:#7a5c3e; }
+ ul { padding-left:1.2em; }
+ hr { border:0; border-top:1px solid var(--line); margin:2.5em 0; }
+ .foot { color:var(--muted); font-size:13px; }
+</style>
+</head>
+<body>
+<div class="wrap">
+ <div class="brand">Designer Wallcoverings</div>
+ <h1>Privacy Policy</h1>
+ <div class="eff">Effective July 14, 2026</div>
+
+ <p>This Privacy Policy explains how Designer Wallcoverings ("we," "us," "our")
+ handles information in connection with our websites at
+ <a href="https://designerwallcoverings.com">designerwallcoverings.com</a> and
+ its subdomains, and our own social-media marketing tools (including the
+ "DW Marketing" application used to schedule and publish content to our own
+ business accounts).</p>
+
+ <h2>1. Information we access and process</h2>
+ <ul>
+ <li><strong>Our own social-media content and insights.</strong> Our marketing
+ tools use the Meta Graph API to publish content to, and read aggregate
+ performance insights (reach, impressions, follower counts) for,
+ <em>our own</em> Designer Wallcoverings business accounts. We do not
+ collect the private data of other users through these tools.</li>
+ <li><strong>Information you give us.</strong> If you contact us (e.g., via a
+ form or email), we receive the details you provide, such as your name,
+ email address, and message.</li>
+ <li><strong>Standard site data.</strong> Like most websites, our servers may
+ log technical information such as IP address, browser type, and pages
+ requested, for security and operational purposes.</li>
+ </ul>
+
+ <h2>2. How we use information</h2>
+ <ul>
+ <li>To create, schedule, and publish our own marketing content.</li>
+ <li>To measure the performance of our own accounts and improve our content.</li>
+ <li>To respond to inquiries and provide customer service.</li>
+ <li>To operate, secure, and maintain our websites and systems.</li>
+ </ul>
+
+ <h2>3. What we do not do</h2>
+ <p>We do <strong>not</strong> sell or rent personal information. We do not use
+ your data for advertising profiling by third parties, and we do not access
+ private data belonging to other people's social-media accounts.</p>
+
+ <h2>4. Third-party platforms</h2>
+ <p>Our marketing tools rely on Meta Platforms, Inc. (Facebook / Instagram).
+ Your use of those platforms is governed by Meta's own policies. We access only
+ the data and permissions necessary to manage our own accounts.</p>
+
+ <h2>5. Data retention</h2>
+ <p>We retain information only as long as needed for the purposes described
+ here or as required by law, after which it is deleted or de-identified.</p>
+
+ <h2>6. Your choices & requests</h2>
+ <p>You may request access to, correction of, or deletion of personal
+ information you have provided to us by emailing
+ <a href="mailto:info@designerwallcoverings.com">info@designerwallcoverings.com</a>.
+ We will respond within a reasonable time.</p>
+
+ <h2>7. Children</h2>
+ <p>Our services are intended for a general, adult, business-and-design
+ audience and are not directed to children under 13.</p>
+
+ <h2>8. Changes</h2>
+ <p>We may update this policy from time to time. Material changes will be
+ reflected by updating the effective date above.</p>
+
+ <h2>9. Contact</h2>
+ <p>Designer Wallcoverings<br>
+ <a href="mailto:info@designerwallcoverings.com">info@designerwallcoverings.com</a></p>
+
+ <hr>
+ <p class="foot">See also our <a href="/terms">Terms of Service</a>.</p>
+</div>
+</body>
+</html>
diff --git a/public/terms.html b/public/terms.html
new file mode 100644
index 0000000..b16caf4
--- /dev/null
+++ b/public/terms.html
@@ -0,0 +1,86 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Terms of Service — Designer Wallcoverings</title>
+<style>
+ :root { --ink:#1a1a1a; --muted:#666; --line:#e5e2dc; --bg:#faf8f4; }
+ * { box-sizing:border-box; }
+ body { margin:0; background:var(--bg); color:var(--ink);
+ font:16px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif; }
+ .wrap { max-width:760px; margin:0 auto; padding:56px 24px 96px; }
+ .brand { font-weight:600; letter-spacing:.18em; text-transform:uppercase; font-size:13px; color:var(--muted); }
+ h1 { font-weight:600; font-size:32px; margin:.35em 0 .15em; letter-spacing:-.01em; }
+ .eff { color:var(--muted); font-size:14px; margin-bottom:2em; }
+ h2 { font-size:18px; margin:2em 0 .4em; }
+ p, li { color:#2a2a2a; }
+ a { color:#7a5c3e; }
+ ul { padding-left:1.2em; }
+ hr { border:0; border-top:1px solid var(--line); margin:2.5em 0; }
+ .foot { color:var(--muted); font-size:13px; }
+</style>
+</head>
+<body>
+<div class="wrap">
+ <div class="brand">Designer Wallcoverings</div>
+ <h1>Terms of Service</h1>
+ <div class="eff">Effective July 14, 2026</div>
+
+ <p>These Terms of Service ("Terms") govern your access to and use of the
+ websites, content, and marketing tools operated by Designer Wallcoverings
+ ("we," "us," "our"), including <a href="https://designerwallcoverings.com">designerwallcoverings.com</a>
+ and its subdomains. By accessing or using our services, you agree to these Terms.</p>
+
+ <h2>1. Use of our services</h2>
+ <p>You may use our websites and content for lawful, personal, and legitimate
+ business purposes. You agree not to misuse the services, interfere with their
+ operation, attempt unauthorized access, or use them to violate any law or the
+ rights of others.</p>
+
+ <h2>2. Marketing tools & social accounts</h2>
+ <p>Our internal marketing application is used solely to manage
+ <em>our own</em> Designer Wallcoverings social-media business accounts (for
+ example, to schedule and publish content and review our own account insights).
+ It is not offered to the public as a standalone service and does not act on
+ behalf of any third party's account.</p>
+
+ <h2>3. Intellectual property</h2>
+ <p>All content on our sites — including product imagery, text, logos, and
+ designs — is owned by Designer Wallcoverings or its licensors and is protected
+ by applicable intellectual-property laws. You may not reproduce, distribute, or
+ create derivative works without our prior written permission.</p>
+
+ <h2>4. Products & information</h2>
+ <p>Product descriptions, availability, and pricing are provided for
+ informational purposes and may change without notice. We make reasonable
+ efforts to keep information accurate but do not warrant that it is complete,
+ current, or error-free.</p>
+
+ <h2>5. Disclaimers</h2>
+ <p>The services and content are provided "as is" and "as available," without
+ warranties of any kind, whether express or implied, to the fullest extent
+ permitted by law.</p>
+
+ <h2>6. Limitation of liability</h2>
+ <p>To the fullest extent permitted by law, Designer Wallcoverings will not be
+ liable for any indirect, incidental, special, consequential, or punitive
+ damages arising from your use of the services.</p>
+
+ <h2>7. Governing law</h2>
+ <p>These Terms are governed by the laws of the State of California, without
+ regard to its conflict-of-laws rules.</p>
+
+ <h2>8. Changes</h2>
+ <p>We may update these Terms from time to time. Continued use of the services
+ after changes take effect constitutes acceptance of the revised Terms.</p>
+
+ <h2>9. Contact</h2>
+ <p>Designer Wallcoverings<br>
+ <a href="mailto:info@designerwallcoverings.com">info@designerwallcoverings.com</a></p>
+
+ <hr>
+ <p class="foot">See also our <a href="/privacy">Privacy Policy</a>.</p>
+</div>
+</body>
+</html>
diff --git a/server.js b/server.js
index f9d153b..cf8fa68 100644
--- a/server.js
+++ b/server.js
@@ -75,7 +75,9 @@ async function serveFile(fp, req, res) {
// must be able to fetch them — so GET /reels/*.mp4 is the ONE unauthenticated path.
// Everything else (console, APIs, data) stays Basic-Auth gated.
const PUBLIC_MEDIA = /^\/reels\/[^/]+\.mp4$/;
-const isPublicMedia = req => (req.method === 'GET' || req.method === 'HEAD') && PUBLIC_MEDIA.test(new URL(req.url, 'http://localhost').pathname);
+// Public legal pages must be readable without auth (Meta app review fetches them).
+const PUBLIC_PAGES = /^\/(privacy|terms)$/;
+const isPublicMedia = req => (req.method === 'GET' || req.method === 'HEAD') && (PUBLIC_MEDIA.test(new URL(req.url, 'http://localhost').pathname) || PUBLIC_PAGES.test(new URL(req.url, 'http://localhost').pathname));
const server = http.createServer(async (req, res) => {
if (!isPublicMedia(req) && !authed(req)) {
@@ -86,6 +88,8 @@ const server = http.createServer(async (req, res) => {
const p = url.pathname;
try {
if (p === '/' ) return await serveFile(join(ROOT, 'public', 'index.html'), req, res);
+ if (p === '/privacy') return await serveFile(join(ROOT, 'public', 'privacy.html'), req, res);
+ if (p === '/terms') return await serveFile(join(ROOT, 'public', 'terms.html'), req, res);
if (p === '/api/reels') {
const fp = join(ROOT, 'data', 'reels.json');
return res.writeHead(200, { 'content-type': 'application/json' }).end(existsSync(fp) ? await readFile(fp) : '[]');
← 59b2d6b build-reel: mux silent AAC track into every reel — IG Reels
·
back to Dw Marketing Reels
·
auto-save: 2026-07-15T07:35:12 (2 files) — data/new-arrivals c5afbac →