Education series · Week

Week 4 — Making it dynamic (drop-in JavaScript)

Form submits. Email arrives. Zero React. Zero servers.

📹 Video shipping soon

Drafted + scripted. Recording in queue. Subscribe to the Founder Plan to be notified the moment it lands.

What you'll walk away with

A scene-by-scene walkthrough of every beat in the video. Plain English. Real numbers. Real workflow.

The walkthrough

  1. Form submits. Email arrives. Zero React. Zero servers.
  2. Education Series · Module 4 · Making It Dynamic
  3. 1. Contact form (POST → email) · 2. Pricing slider · 3. Newsletter signup
  4. Why not React
  5. The form file open in Cursor
  6. js/contact.js
  7. form.addEventListener('submit', async (e) => { e.preventDefault(); ... })
  8. const res = await fetch('/.netlify/functions/contact', { method: 'POST', body: ... })
  9. const data = Object.fromEntries(new FormData(form));
  10. Toggling a .is-success class · CSS shows a green checkmark
  11. netlify/functions/contact.js
  12. exports.handler = async (event) => { ... return { statusCode: 200 }; }
  13. const data = JSON.parse(event.body); then validation
  14. import postmark from 'postmark' then send call
  15. Setting POSTMARK_TOKEN in Netlify dashboard
  16. Push, wait 30s, fill the form, watch email arrive
  17. Adding a range input + price display
  18. slider.addEventListener('input', updatePrice)
  19. const price = base + (slider.value * unit);
  20. Dragging in browser, price ticks up smoothly
  21. New section with email input + button
  22. netlify/functions/subscribe.js
  23. import Database from 'better-sqlite3'
  24. db.prepare('INSERT INTO subscribers (email) VALUES (?)').run(email)
  25. Template with a confirm link
  26. Try/catch in both the client JS and the function
  27. required attributes · pattern attribute · novalidate disable
  28. Still 100/100/100/100 — JavaScript hasn't broken our score
  29. First load: 12KB total. Page weight stays small.
  30. 1. Forgetting preventDefault · 2. Not handling errors · 3. Trusting client validation · 4. Mutating innerHTML
  31. Real-time multi-user · big SPA · complex state
  32. Postmark free tier · Netlify Functions free tier · SQLite $0
  33. Static + Function: 60ms response · WP: 800ms response
  34. drop-in JS
  35. HOMEWORK: Add ONE form to your site that triggers an email. Push it. Send me the URL.
  36. NEXT WEEK: WordPress — when it makes sense and when it doesn't
  37. localmodeldojo.com · LAUNCH30 · 30 days only

Cut your AI bill 90%+

I built Local Model Dojo so the same kind of bot work that costs $100/mo on the Claude or OpenAI API runs on hardware you already own. Founder pricing locks in for the life of your account.

See Founder pricing → Code LAUNCH30 · 30-day window

← Week 3 — Your first real website (HTML+CSS, no framework) Week 5 — Converting to WordPress (when it makes sense) →

— Jake Morris · Oklahoma veteran · localmodeldojo.com