[object Object]

← 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

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 &amp; 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 &amp; 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 &amp; 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 →