<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: PaiVelmoxia</title>
    <description>The latest articles on DEV Community by PaiVelmoxia (@paivelmoxia).</description>
    <link>https://dev.to/paivelmoxia</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4205616%2F46db3ef5-5c60-4cce-8cbd-77c9a686aa7f.png</url>
      <title>DEV Community: PaiVelmoxia</title>
      <link>https://dev.to/paivelmoxia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paivelmoxia"/>
    <language>en</language>
    <item>
      <title>I generate a week of social posts from the real sky, in the browser</title>
      <dc:creator>PaiVelmoxia</dc:creator>
      <pubDate>Thu, 29 Oct 2026 00:25:34 +0000</pubDate>
      <link>https://dev.to/paivelmoxia/i-generate-a-week-of-social-posts-from-the-real-sky-in-the-browser-3cao</link>
      <guid>https://dev.to/paivelmoxia/i-generate-a-week-of-social-posts-from-the-real-sky-in-the-browser-3cao</guid>
      <description>&lt;p&gt;&lt;em&gt;Second post in a small series about building a family games site with AI's help. I'm not a programmer; an AI wrote most of this code with me, and I test everything on a phone.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our site has a free birth chart and a weekly reading for the 12 zodiac signs. Once a week I need posts for the social networks: one text with all 12 signs and 12 images, one per sign, in four languages. Writing that by hand every Monday would kill the project, so we built a small generator into our admin panel. Here is how it works, and where I had to be careful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Astrology is symbolic, the sky is not
&lt;/h2&gt;

&lt;p&gt;Let me be upfront: the reading is a symbolic one, and the page says so. But the positions it starts from are real. Where the Sun, the Moon, Mercury, Venus and Mars are this week is plain astronomy, and getting that right was the fun part.&lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://github.com/cosinekitty/astronomy" rel="noopener noreferrer"&gt;astronomy-engine&lt;/a&gt; (MIT licence), which runs entirely in the browser. No server, no API key, no quota.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MakeTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sun&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SunPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;elon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EclipticGeoMoon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mercury&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ven&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Venus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Ecliptic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GeoVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;elon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;deg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="nx"&gt;deg&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0 = Aries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each sign is a 30° slice of the ecliptic, so turning a longitude into a sign is one line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrograde, the lazy way
&lt;/h2&gt;

&lt;p&gt;"Mercury is retrograde" is the line people actually read. Instead of looking up tables, we check whether the planet's longitude is going backwards: compare its position 12 hours later with 12 hours earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isRetro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;432&lt;/span&gt;&lt;span class="nx"&gt;e5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;432&lt;/span&gt;&lt;span class="nx"&gt;e5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// moved "backwards" around the circle&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;% 360&lt;/code&gt; dance matters: a planet going from 359° to 1° moved forward 2°, not backwards 358°.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which week is "this week"?
&lt;/h2&gt;

&lt;p&gt;This sounds trivial and wasn't. If I open the panel on a Friday, I want next week's posts, not the week that is almost over. The rule we settled on: early in the week it shows the current week, and towards the end of the week it jumps to the next one. There is also a button to move one week ahead, so I can prepare posts in advance.&lt;/p&gt;

&lt;h2&gt;
  
  
  From positions to a reading
&lt;/h2&gt;

&lt;p&gt;For each sign, the generator takes the middle of the week and asks where the Sun, Venus and Mars fall counted from that sign. That gives one of twelve "areas of life" (yourself, money, home, love, work, and so on), each written once per language. Then it walks the seven days and marks the days when the Moon is in a friendly position, in your own sign, or in a tense one.&lt;/p&gt;

&lt;p&gt;So the text is assembled, not invented each time. I wrote the building blocks once, with care, in four languages, and the sky picks which ones apply.&lt;/p&gt;

&lt;h2&gt;
  
  
  The output
&lt;/h2&gt;

&lt;p&gt;In the panel, for each language, I get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the post text with the 12 signs and a link to the full week on the site;&lt;/li&gt;
&lt;li&gt;12 images of 1080 × 1350, one per sign, ready to download.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The link carries a small &lt;code&gt;utm_source&lt;/code&gt; tag so our cookie-free counter can tell how many people came from those posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Put the boring weekly work in the admin panel.&lt;/strong&gt; If a task repeats every week, it will eventually be skipped. A button that does it in seconds won't be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real data makes symbolic content more honest.&lt;/strong&gt; People can check that Mercury really is retrograde. That builds more trust than vague text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge cases hide in dates.&lt;/strong&gt; Week boundaries, time zones and the 360° wrap caused more bugs than the astronomy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say what is symbolic.&lt;/strong&gt; One line under the reading is enough, and nobody complained.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The chart and the weekly reading are free, with no download and no sign-up: &lt;a href="https://velmoxia.com/en/zodiac/?utm_source=dev" rel="noopener noreferrer"&gt;velmoxia.com/en/zodiac&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you know astronomy better than I do (that is not hard), I'd love to hear what you would do differently, especially for the Moon, which moves a whole sign every two and a half days.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>astronomy</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I generate a week of social posts from the real sky, in the browser</title>
      <dc:creator>PaiVelmoxia</dc:creator>
      <pubDate>Wed, 28 Oct 2026 12:51:34 +0000</pubDate>
      <link>https://dev.to/paivelmoxia/i-generate-a-week-of-social-posts-from-the-real-sky-in-the-browser-414k</link>
      <guid>https://dev.to/paivelmoxia/i-generate-a-week-of-social-posts-from-the-real-sky-in-the-browser-414k</guid>
      <description>&lt;p&gt;&lt;em&gt;Second post in a small series about building a family games site with AI's help. I'm not a programmer; an AI wrote most of this code with me, and I test everything on a phone. This post was drafted with AI and reviewed by me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our site has a free birth chart and a weekly reading for the 12 zodiac signs. Once a week I need posts for the social networks: one text with all 12 signs and 12 images, one per sign, in four languages. Writing that by hand every Monday would kill the project, so we built a small generator into our admin panel. Here is how it works, and where I had to be careful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Astrology is symbolic, the sky is not
&lt;/h2&gt;

&lt;p&gt;Let me be upfront: the reading is a symbolic one, and the page says so. But the positions it starts from are real. Where the Sun, the Moon, Mercury, Venus and Mars are this week is plain astronomy, and getting that right was the fun part.&lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://github.com/cosinekitty/astronomy" rel="noopener noreferrer"&gt;astronomy-engine&lt;/a&gt; (MIT licence), which runs entirely in the browser. No server, no API key, no quota.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MakeTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sun&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SunPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;elon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EclipticGeoMoon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mercury&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ven&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Venus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Ecliptic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GeoVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;elon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;deg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="nx"&gt;deg&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0 = Aries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each sign is a 30° slice of the ecliptic, so turning a longitude into a sign is one line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrograde, the lazy way
&lt;/h2&gt;

&lt;p&gt;"Mercury is retrograde" is the line people actually read. Instead of looking up tables, we check whether the planet's longitude is going backwards: compare its position 12 hours later with 12 hours earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isRetro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;432&lt;/span&gt;&lt;span class="nx"&gt;e5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;432&lt;/span&gt;&lt;span class="nx"&gt;e5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// moved "backwards" around the circle&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;% 360&lt;/code&gt; dance matters: a planet going from 359° to 1° moved forward 2°, not backwards 358°.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which week is "this week"?
&lt;/h2&gt;

&lt;p&gt;This sounds trivial and wasn't. If I open the panel on a Friday, I want next week's posts, not the week that is almost over. The rule we settled on: early in the week it shows the current week, and towards the end of the week it jumps to the next one. There is also a button to move one week ahead, so I can prepare posts in advance.&lt;/p&gt;

&lt;h2&gt;
  
  
  From positions to a reading
&lt;/h2&gt;

&lt;p&gt;For each sign, the generator takes the middle of the week and asks where the Sun, Venus and Mars fall counted from that sign. That gives one of twelve "areas of life" (yourself, money, home, love, work, and so on), each written once per language. Then it walks the seven days and marks the days when the Moon is in a friendly position, in your own sign, or in a tense one.&lt;/p&gt;

&lt;p&gt;So the text is assembled, not invented each time. I wrote the building blocks once, with care, in four languages, and the sky picks which ones apply.&lt;/p&gt;

&lt;h2&gt;
  
  
  The output
&lt;/h2&gt;

&lt;p&gt;In the panel, for each language, I get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the post text with the 12 signs and a link to the full week on the site;&lt;/li&gt;
&lt;li&gt;12 images of 1080 × 1350, one per sign, ready to download.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The link carries a small &lt;code&gt;?s=&lt;/code&gt; tag so our cookie-free counter can tell how many people came from those posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Put the boring weekly work in the admin panel.&lt;/strong&gt; If a task repeats every week, it will eventually be skipped. A button that does it in seconds won't be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real data makes symbolic content more honest.&lt;/strong&gt; People can check that Mercury really is retrograde. That builds more trust than vague text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge cases hide in dates.&lt;/strong&gt; Week boundaries, time zones and the 360° wrap caused more bugs than the astronomy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say what is symbolic.&lt;/strong&gt; One line under the reading is enough, and nobody complained.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The chart and the weekly reading are free, with no download and no sign-up: &lt;a href="https://velmoxia.com/en/zodiac/?s=dev" rel="noopener noreferrer"&gt;velmoxia.com/en/zodiac&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you know astronomy better than I do (that is not hard), I'd love to hear what you would do differently, especially for the Moon, which moves a whole sign every two and a half days.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>astronomy</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I'm not a programmer. I built 70+ free browser games for my kids with AI. Here's what I learned</title>
      <dc:creator>PaiVelmoxia</dc:creator>
      <pubDate>Sun, 25 Oct 2026 00:06:20 +0000</pubDate>
      <link>https://dev.to/paivelmoxia/im-not-a-programmer-i-built-70-free-browser-games-for-my-kids-with-ai-heres-what-i-learned-3p0l</link>
      <guid>https://dev.to/paivelmoxia/im-not-a-programmer-i-built-70-free-browser-games-for-my-kids-with-ai-heres-what-i-learned-3p0l</guid>
      <description>&lt;p&gt;I'm not a programmer. My kids asked me for a game "with our rules", and I didn't know how to make one. So I asked an AI to help me.&lt;/p&gt;

&lt;p&gt;One of the first games was a small platformer with my daughter as the hero. Today there are more than 70 free games on the site, in four languages, and the whole family tests them. This is what I learned along the way, for anyone else who is "not technical" and wants to try.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack is boring on purpose
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WordPress&lt;/strong&gt; on managed hosting, because I needed something I could not break easily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each game is one self-contained page&lt;/strong&gt;: HTML, CSS and plain JavaScript, no framework, no build step. The AI writes it, I test it on a phone, we fix it, repeat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Code Snippets plugin&lt;/strong&gt; for everything custom on the server side: a small admin panel, our own cookie-free visit counter, a daily report.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polylang&lt;/strong&gt; for Portuguese (Portugal and Brazil), English and Spanish.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Android app&lt;/strong&gt; that is just the website wrapped as a Trusted Web Activity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No React, no game engine. When you can't read code well, fewer moving parts means fewer things you can't debug.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI was great at
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Turning house rules into code.&lt;/strong&gt; "In our family, Sueca is played like this" is a perfectly good spec.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boring but important stuff&lt;/strong&gt;: saving progress, fullscreen on mobile, translations, accessibility labels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explaining things.&lt;/strong&gt; I now understand caching, service workers and why my own stats were wrong, because I kept asking "why?" until it made sense.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What was hard
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Card game opponents.&lt;/strong&gt; Making a computer partner bid Bridge in a way that feels human took many rounds. The trick that worked: add a teacher. In our Bridge there is an owl called Mox who explains why each bid makes sense, so when the bot does something odd, at least it tells you its reasoning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rules have dialects.&lt;/strong&gt; Every family plays Sueca or Truco a little differently, so each game needs clear rules on screen and sensible defaults.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listening to feedback.&lt;/strong&gt; A developer community told me my pages were cached for 31 days. They were. My host's gateway was overriding my headers, so the fix was a service worker that revalidates pages on every visit. The same people asked for a timer in Spider Solitaire, which was already there but too hidden.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measuring honestly.&lt;/strong&gt; One day my counter said 55 visits and 1 game opened. The bug was mine: I only counted a game as "opened" when it went fullscreen. Now it counts the first tap.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd tell other parents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start with one small game your kid actually wants. Their excitement is the best project manager.&lt;/li&gt;
&lt;li&gt;Test on the real device they use. Most of my bugs only appeared on a phone.&lt;/li&gt;
&lt;li&gt;Say out loud that AI helped. Nobody minded, and people were curious about the process.&lt;/li&gt;
&lt;li&gt;Ask the AI to explain, not just to fix. That is how you stop being stuck.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Everything is free, with no download and no sign-up. A good place to start is the &lt;a href="https://velmoxia.com/en/games/bridge/?s=dev" rel="noopener noreferrer"&gt;Bridge game with the owl teacher&lt;/a&gt;, or the &lt;a href="https://velmoxia.com/en/games/?s=dev" rel="noopener noreferrer"&gt;full list of games&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'd love feedback from people who actually know what they're doing: what would you change in this setup?&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>gamedev</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
