<?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: Rayyan Aljamal</title>
    <description>The latest articles on DEV Community by Rayyan Aljamal (@rayan_aljamal_f93e2a391d0).</description>
    <link>https://dev.to/rayan_aljamal_f93e2a391d0</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%2F4000655%2Ffb2dd493-789a-4318-91bf-763caa4b0093.png</url>
      <title>DEV Community: Rayyan Aljamal</title>
      <link>https://dev.to/rayan_aljamal_f93e2a391d0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rayan_aljamal_f93e2a391d0"/>
    <language>en</language>
    <item>
      <title>How I'm Making My Portfolio Findable by Google and AI Search</title>
      <dc:creator>Rayyan Aljamal</dc:creator>
      <pubDate>Mon, 09 Nov 2026 06:08:00 +0000</pubDate>
      <link>https://dev.to/rayan_aljamal_f93e2a391d0/how-im-making-my-portfolio-findable-by-google-and-ai-search-1b31</link>
      <guid>https://dev.to/rayan_aljamal_f93e2a391d0/how-im-making-my-portfolio-findable-by-google-and-ai-search-1b31</guid>
      <description>&lt;p&gt;My portfolio is a Next.js site with 17 live projects. In early November I opened Google Search Console and found the truth: one search click in total, one page indexed, eight pages not indexed. Google knew the site existed and had mostly not bothered to read it. I spent a week fixing that. This is what I did, in the order I did it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real problem was indexing, not content
&lt;/h2&gt;

&lt;p&gt;I researched first, and the bottleneck was not the writing or the design. It was that Google had not indexed the pages. AI search has the same problem in a different shape: most AI crawlers do not run JavaScript, so anything that only appears after the page loads is invisible to them. That decided the whole plan. Put the facts in the first HTML the server sends.&lt;/p&gt;

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

&lt;p&gt;I split the site into English and Arabic route groups, with self-canonicals and reciprocal hreflang, so each language is its own page instead of one page with a toggle. I rewrote llms.txt, added a full llms-full.txt that is generated on every build and lists all 17 projects, rebuilt the sitemap to 40 URLs, and resubmitted everything to IndexNow, which answered 202. The FAQ grew from 5 questions to 8 in both languages, with matching FAQPage structured data per language, and robots.txt now explicitly allows 11 AI crawlers.&lt;/p&gt;

&lt;p&gt;Two honest notes. First, the research says llms.txt is barely read: in one log study across 83 sites over three months, GPTBot fetched it 7 times and ClaudeBot 9 times. I did it anyway because it costs nothing, but it is not the lever. Second, I removed every mention of one city from the site and deleted its page, knowing it means giving up ranking for that city's searches. That was a deliberate trade, not an accident.&lt;/p&gt;

&lt;p&gt;I also removed the contact form and replaced it with social links and an email card, because a form nobody uses is just weight on the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do not know yet
&lt;/h2&gt;

&lt;p&gt;Whether any of it worked. The check is Friday 13 November, when I look at Search Console again and compare against the baseline: 1 indexed page, 8 not indexed, 1 click. Two articles on dev.to went live on 9 November as part of the same push, one about the schools dataset and one about a database migration, to give Google fresh pages to find. If the numbers move, I will write the follow-up with the real numbers. If they do not, I will say that too.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built a Roblox RPG With 205 Scripts, From My Phone</title>
      <dc:creator>Rayyan Aljamal</dc:creator>
      <pubDate>Mon, 09 Nov 2026 06:05:55 +0000</pubDate>
      <link>https://dev.to/rayan_aljamal_f93e2a391d0/i-built-a-roblox-rpg-with-205-scripts-from-my-phone-3j3l</link>
      <guid>https://dev.to/rayan_aljamal_f93e2a391d0/i-built-a-roblox-rpg-with-205-scripts-from-my-phone-3j3l</guid>
      <description>&lt;p&gt;I do not own a computer. Everything I build, I build from my phone. My biggest project is Hearthmear, a Roblox RPG I have been building since October 2026. It has 10 dungeons, 7 bosses, 17 enemy types, three classes, crafting, housing, mail, trading, and 205 scripts. This is how that works when your only device is a phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The workflow is files, not Studio
&lt;/h2&gt;

&lt;p&gt;Roblox Studio does not run on a phone, so I work in place files. I download the game's .rbxl file, send it to my AI assistant, and get back an edited file. When I build something myself in Studio, I send that file the same way and the work builds on it. Publishing goes through the Roblox Open Cloud API: one command uploads the file and it goes live as the next version. The live game is on version 141 now, and every version went up that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the game actually is
&lt;/h2&gt;

&lt;p&gt;You pick one of three classes at the start, Hearthguard, Duskrunner or Emberwrought, and the choice is locked forever. XP tiers at 150, 400, 1000, 2000 and 4000 unlock moves: Dodge Roll, Heavy Strike, Parry, Battle Shout and Leap Slam. There are seven original dungeons plus three newer areas, each with its own monsters and a boss at the end.&lt;/p&gt;

&lt;p&gt;The part players remember is the cult. The Ossuary Choir can capture you, lock you in a prison, and sacrifice you if you do not escape within 48 real minutes. Even god mode does not save you from the sacrifice. That rule was a deliberate choice: the danger has to be real or the game is boring.&lt;/p&gt;

&lt;h2&gt;
  
  
  No AI assets, ever
&lt;/h2&gt;

&lt;p&gt;Nothing in the game is AI-generated. Models are built from parts in Studio or come from the Creator Store with verified IDs, and every image is checked the same way. That rule is why the game looks like itself instead of like every other AI-made game. It is slower, but the slowness is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  My phone is the test suite
&lt;/h2&gt;

&lt;p&gt;The assistant I work with cannot see or hear the game, so my playtest on my phone is the only real check that a change feels right. The loop is: small change, read the code back, publish, playtest, report what broke with a screenshot. The screenshots are the test suite. When something feels wrong I say so in one word and we fix it, we never argue for the broken version.&lt;/p&gt;

&lt;p&gt;The game is live at &lt;a href="https://www.roblox.com/games/135378269095329/hearthmear" rel="noopener noreferrer"&gt;https://www.roblox.com/games/135378269095329/hearthmear&lt;/a&gt;. If you are building from a phone too, the lesson is simple: you do not need a computer, you need a tight loop and someone, or something, that can edit the file you send it.&lt;/p&gt;

</description>
      <category>roblox</category>
      <category>lua</category>
      <category>gamedev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Replaced MongoDB with Turso Without Touching Roughly 1,250 Database Calls</title>
      <dc:creator>Rayyan Aljamal</dc:creator>
      <pubDate>Mon, 09 Nov 2026 06:01:48 +0000</pubDate>
      <link>https://dev.to/rayan_aljamal_f93e2a391d0/i-replaced-mongodb-with-turso-without-touching-roughly-1250-database-calls-178k</link>
      <guid>https://dev.to/rayan_aljamal_f93e2a391d0/i-replaced-mongodb-with-turso-without-touching-roughly-1250-database-calls-178k</guid>
      <description>&lt;p&gt;In October 2026, I moved the Future Thinkers Club platform off MongoDB and onto Turso. The interesting part is not the move itself. It is that the application code barely noticed: roughly 1,250 database calls stayed exactly as they were.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why move at all
&lt;/h2&gt;

&lt;p&gt;The platform runs on Vercel, on serverless functions. The native database driver path did not work there, so the fix was a pure-Python client that talks to Turso over HTTP. No native driver, no compiled dependency, just HTTP requests from Python. That one decision shaped the whole migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The adapter trick
&lt;/h2&gt;

&lt;p&gt;Instead of rewriting every query in the app, I wrote a MongoDB-compatible adapter on top of Turso. The app keeps calling the same functions it always called, and the adapter translates them into Turso operations underneath. The interface stayed, the engine changed.&lt;/p&gt;

&lt;p&gt;File storage moved the same way. Files used to live in GridFS; now they live in a single Turso table called &lt;code&gt;fs_files&lt;/code&gt;, with a path, the file data as a BLOB, a content type, and metadata. The storage functions kept their exact signatures: save a file, read a file, delete a file. The rest of the app never knew anything changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;The migration went live with the health endpoint reporting the database up, and the platform kept working through the switch: logins, clubs, messages, book uploads, all on the new database. No data loss, no rewrite of the application, and no downtime for the students using it.&lt;/p&gt;

&lt;p&gt;The lesson I took from it is one I now use on every project: when you need to change infrastructure, change it behind an interface you already own. If your app talks to a database through one adapter, you can swap the database. If it talks to MongoDB in 1,250 different places, you cannot.&lt;/p&gt;

&lt;p&gt;The platform is live at &lt;a href="https://f-thinkers.vercel.app" rel="noopener noreferrer"&gt;https://f-thinkers.vercel.app&lt;/a&gt;, and it is one of the 17 projects on my portfolio at &lt;a href="https://rayyans-showroom.vercel.app/projects/future-thinkers" rel="noopener noreferrer"&gt;https://rayyans-showroom.vercel.app/projects/future-thinkers&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>database</category>
      <category>serverless</category>
    </item>
    <item>
      <title>I Put Every School in Jordan Into One API: 2,601 Schools, 42 Directorates</title>
      <dc:creator>Rayyan Aljamal</dc:creator>
      <pubDate>Mon, 09 Nov 2026 05:49:52 +0000</pubDate>
      <link>https://dev.to/rayan_aljamal_f93e2a391d0/i-put-every-school-in-jordan-into-one-api-2601-schools-42-directorates-34gf</link>
      <guid>https://dev.to/rayan_aljamal_f93e2a391d0/i-put-every-school-in-jordan-into-one-api-2601-schools-42-directorates-34gf</guid>
      <description>&lt;p&gt;I build websites for a living, but the project I am proudest of is the platform for the Future Thinkers Club, a club for Jordanian school students who want to build things, read together, and start small projects. The platform lives at &lt;a href="https://f-thinkers.vercel.app" rel="noopener noreferrer"&gt;https://f-thinkers.vercel.app&lt;/a&gt;, and one of its most useful parts is something you never see on the homepage: a complete dataset of every school in Jordan.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: students need to pick their school
&lt;/h2&gt;

&lt;p&gt;When a student signs up, they pick their school. That sounds simple until you ask where the list comes from. Jordan has thousands of schools, grouped by governorate and then by directorate, the administrative areas the Ministry of Education uses. There was no tidy list I could just plug in, so I built one.&lt;/p&gt;

&lt;p&gt;The dataset covers 12 governorates, 42 directorates, and 2,601 schools, ordered by the Ministry's official directorate structure. The API returns real data: ask for a directorate and you get its schools, ask for a governorate and you get its directorates.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it fits into the platform
&lt;/h2&gt;

&lt;p&gt;The platform itself is React on the frontend and Python on the backend, with Turso as the database. The schools data sits behind an API endpoint, so the signup form, the school directory, and anything else that needs a school list all read from the same source. One dataset, used everywhere, instead of a copy pasted into every page.&lt;/p&gt;

&lt;p&gt;Getting the structure right mattered more than getting it fast. A school in the wrong directorate is worse than a missing school, because a student trusting the list would land in the wrong place. So the data follows the official structure: governorate, then directorate, then school.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it enables
&lt;/h2&gt;

&lt;p&gt;With the dataset in place, students from different schools across Jordan can find each other on the same platform, join the same club, and form teams across schools. A school list sounds like boring infrastructure, and it is. But it is the piece that makes everything else on the platform work: you cannot network students across schools if the platform does not know which schools exist.&lt;/p&gt;

&lt;p&gt;The project is one of the 17 live builds on my portfolio at &lt;a href="https://rayyans-showroom.vercel.app/projects/future-thinkers" rel="noopener noreferrer"&gt;https://rayyans-showroom.vercel.app/projects/future-thinkers&lt;/a&gt;. If you are building anything that needs a real, structured dataset, my advice is simple: spend the time on the structure first. The features you build on top of it will be easy. The features you build on a messy dataset will not.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>react</category>
      <category>database</category>
    </item>
  </channel>
</rss>
