<?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: Graham McCann</title>
    <description>The latest articles on DEV Community by Graham McCann (@graham23s).</description>
    <link>https://dev.to/graham23s</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%2F3708887%2F61532366-8037-4c78-a5d5-5e8f01bc5785.png</url>
      <title>DEV Community: Graham McCann</title>
      <link>https://dev.to/graham23s</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/graham23s"/>
    <language>en</language>
    <item>
      <title>Technical SEO Checks I Run Before Writing More Content</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Sat, 22 Aug 2026 09:01:59 +0000</pubDate>
      <link>https://dev.to/graham23s/technical-seo-checks-i-run-before-writing-more-content-495h</link>
      <guid>https://dev.to/graham23s/technical-seo-checks-i-run-before-writing-more-content-495h</guid>
      <description>&lt;p&gt;“We need more content” is one of the most common conclusions in SEO.&lt;/p&gt;

&lt;p&gt;Sometimes it is right. Often it arrives too early.&lt;/p&gt;

&lt;p&gt;If search engines cannot reliably crawl, understand or index the pages already on a site, another twenty articles just create a larger pile of URLs with the same problem. Before planning content, I run a technical pass in a fixed order.&lt;/p&gt;

&lt;p&gt;It is not glamorous, but it stops expensive work being built on a weak base.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Check the actual HTTP response
&lt;/h2&gt;

&lt;p&gt;I start with the page itself, outside the browser interface.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -I https://example.com/service-page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For an indexable page, I normally expect a clean 200 response. A redirect may be intentional, but chains and loops need attention. A page can also look normal in a browser while behaving like a soft 404 because the content is thin, missing or replaced by an error message.&lt;/p&gt;

&lt;p&gt;I check representative URLs from every important template:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the homepage&lt;/li&gt;
&lt;li&gt;service and category pages&lt;/li&gt;
&lt;li&gt;location pages&lt;/li&gt;
&lt;li&gt;articles&lt;/li&gt;
&lt;li&gt;paginated pages&lt;/li&gt;
&lt;li&gt;filtered or parameterised URLs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One healthy page does not prove that the whole site is healthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Read the robots and canonical instructions together
&lt;/h2&gt;

&lt;p&gt;A page can be blocked or devalued in several different places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;robots.txt&lt;/li&gt;
&lt;li&gt;a meta robots tag&lt;/li&gt;
&lt;li&gt;an X-Robots-Tag HTTP header&lt;/li&gt;
&lt;li&gt;a canonical pointing somewhere else&lt;/li&gt;
&lt;li&gt;an authentication or firewall rule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These instructions need to agree.&lt;/p&gt;

&lt;p&gt;A surprisingly common setup is an indexable page with a canonical to the wrong host, protocol or URL variant. I choose one version of the domain, one trailing-slash policy and one protocol, then make internal links, canonicals and sitemap entries use it consistently.&lt;/p&gt;

&lt;p&gt;I also check rendered HTML. If a canonical or robots directive is injected by JavaScript, the source and rendered versions may not tell the same story.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Treat the sitemap as an inventory, not a repair tool
&lt;/h2&gt;

&lt;p&gt;An XML sitemap helps discovery. It does not force indexing.&lt;/p&gt;

&lt;p&gt;I want it to contain canonical, indexable URLs that return 200. Redirects, deleted pages, duplicates and private areas do not belong there.&lt;/p&gt;

&lt;p&gt;For a small site, I compare the sitemap against the pages the business actually considers important. This often reveals both problems at once: URLs in the sitemap that should not exist, and valuable pages that have been left out.&lt;/p&gt;

&lt;p&gt;A sitemap's lastmod value should also mean something. Updating every timestamp on every deployment teaches crawlers that the field is unreliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Find pages with no internal route
&lt;/h2&gt;

&lt;p&gt;A URL in a sitemap can still be an orphan.&lt;/p&gt;

&lt;p&gt;Search engines learn a great deal from internal links: which pages matter, how topics relate and what language describes a destination. A service page linked from the main navigation and relevant articles has a very different position from one that exists only in an XML file.&lt;/p&gt;

&lt;p&gt;I check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the click depth from the homepage&lt;/li&gt;
&lt;li&gt;broken internal links&lt;/li&gt;
&lt;li&gt;pages with no incoming links&lt;/li&gt;
&lt;li&gt;repeated links to irrelevant pages&lt;/li&gt;
&lt;li&gt;anchor text that says nothing about the destination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I do not try to force every page into the navigation. The aim is to create sensible routes a visitor might genuinely follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Validate structured data against what visitors can see
&lt;/h2&gt;

&lt;p&gt;Structured data is useful when it accurately describes the page. It is not a place to add facts that the page itself does not support.&lt;/p&gt;

&lt;p&gt;A basic service business might use Organization, LocalBusiness, Service, BreadcrumbList or FAQPage, depending on the content. The correct type matters less than the truthfulness and consistency of the properties.&lt;/p&gt;

&lt;p&gt;I validate the JSON-LD, then manually compare names, URLs, phone numbers, addresses, prices and opening hours with the visible page.&lt;/p&gt;

&lt;p&gt;Invalid markup is a technical bug. Valid markup that exaggerates the page is a trust problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Look at performance by template
&lt;/h2&gt;

&lt;p&gt;A sitewide performance score can hide the useful detail.&lt;/p&gt;

&lt;p&gt;The homepage might be fast while every service page loads a huge hero image. Blog posts might shift because an advert or embedded widget has no reserved space. A booking page may respond slowly because it waits on several third-party scripts.&lt;/p&gt;

&lt;p&gt;I review the main templates and pay particular attention to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Largest Contentful Paint, usually the hero image or heading&lt;/li&gt;
&lt;li&gt;Interaction to Next Paint, often affected by heavy JavaScript&lt;/li&gt;
&lt;li&gt;Cumulative Layout Shift from images, fonts and injected elements&lt;/li&gt;
&lt;li&gt;server response time&lt;/li&gt;
&lt;li&gt;unused third-party code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fix is frequently ordinary: resize an image, set dimensions, preload the right font, remove a script or avoid loading a widget before it is needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Check whether each page has a distinct job
&lt;/h2&gt;

&lt;p&gt;Technical health cannot rescue a group of pages that all answer the same query in almost the same way.&lt;/p&gt;

&lt;p&gt;For each important URL, I write down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the visitor's likely intent&lt;/li&gt;
&lt;li&gt;the main topic&lt;/li&gt;
&lt;li&gt;the unique information on the page&lt;/li&gt;
&lt;li&gt;the action the visitor can take&lt;/li&gt;
&lt;li&gt;the closest competing page on the same site&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If two URLs have the same answer, I decide whether to combine them, differentiate them or choose one canonical version. Writing more text onto both rarely solves the overlap.&lt;/p&gt;

&lt;p&gt;Titles and H1s should be descriptive, but the real test is the body. A page needs to fulfil the promise made in the search result.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Verify after changes go live
&lt;/h2&gt;

&lt;p&gt;The audit is not finished when a spreadsheet is delivered.&lt;/p&gt;

&lt;p&gt;After deployment, I recheck response codes, canonicals, robots directives, structured data and sitemap entries. I use Search Console's URL Inspection for a sample of important pages and watch crawl or server logs where they are available.&lt;/p&gt;

&lt;p&gt;Indexing is not instant, and not every valid page deserves to rank. The goal of the technical pass is narrower: remove accidental barriers and give worthwhile pages a clear, consistent structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  My short pre-content checklist
&lt;/h2&gt;

&lt;p&gt;Before commissioning more articles, I want to be able to say yes to these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do priority URLs return the intended status code?&lt;/li&gt;
&lt;li&gt;Are they indexable and self-canonical?&lt;/li&gt;
&lt;li&gt;Are domain and URL variants consistent?&lt;/li&gt;
&lt;li&gt;Does the sitemap list only useful canonical URLs?&lt;/li&gt;
&lt;li&gt;Can visitors reach important pages through internal links?&lt;/li&gt;
&lt;li&gt;Does structured data match visible information?&lt;/li&gt;
&lt;li&gt;Are the main templates usable and reasonably fast?&lt;/li&gt;
&lt;li&gt;Does every page have a distinct purpose?&lt;/li&gt;
&lt;li&gt;Have the deployed fixes been verified?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only then do I move on to content planning.&lt;/p&gt;

&lt;p&gt;This is the same order I use at &lt;a href="https://www.gm-seo-services.com/" rel="noopener noreferrer"&gt;GM SEO Services&lt;/a&gt;: fix crawl and indexation problems first, then invest in content.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>performance</category>
      <category>marketing</category>
    </item>
    <item>
      <title>The Hidden Complexity of Appointment Availability</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Sat, 22 Aug 2026 08:44:08 +0000</pubDate>
      <link>https://dev.to/graham23s/the-hidden-complexity-of-appointment-availability-4fpp</link>
      <guid>https://dev.to/graham23s/the-hidden-complexity-of-appointment-availability-4fpp</guid>
      <description>&lt;p&gt;Appointment booking looks simple until you try to build it.&lt;/p&gt;

&lt;p&gt;At first, the problem appears to be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the business opening hours.&lt;/li&gt;
&lt;li&gt;Remove times that are already booked.&lt;/li&gt;
&lt;li&gt;Show what remains.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That version works for a demo. It does not survive contact with a real therapist, tutor, salon or consultant.&lt;/p&gt;

&lt;p&gt;While building OpenSlot, I found that availability is less like a calendar and more like a small rules engine. A time is bookable only when several independent constraints agree.&lt;/p&gt;

&lt;h2&gt;
  
  
  A slot is more than a start time
&lt;/h2&gt;

&lt;p&gt;A useful slot needs at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a start and end time&lt;/li&gt;
&lt;li&gt;the service duration&lt;/li&gt;
&lt;li&gt;a staff member&lt;/li&gt;
&lt;li&gt;the business time zone&lt;/li&gt;
&lt;li&gt;minimum booking notice&lt;/li&gt;
&lt;li&gt;buffers before or after the appointment&lt;/li&gt;
&lt;li&gt;working hours and breaks&lt;/li&gt;
&lt;li&gt;time off&lt;/li&gt;
&lt;li&gt;existing bookings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I keep the service duration separate from its buffers. A 60-minute consultation with a 15-minute clean-up period occupies 75 minutes of the diary, but the customer should still see a 60-minute service.&lt;/p&gt;

&lt;p&gt;A simplified rule might look like this:&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;canBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;existingBookings&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;occupiedUntil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;addMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferAfter&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;isInsideWorkingHours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;occupiedUntil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nf"&gt;hasEnoughNotice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minimumNotice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;overlapsTimeOff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;occupiedUntil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeOff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;overlapsBooking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;occupiedUntil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;existingBookings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is not the difficult part. The difficult part is agreeing on what every boundary means.&lt;/p&gt;

&lt;p&gt;If one appointment ends at 11:00, can the next start at 11:00? Usually yes, unless a buffer applies. Are end times inclusive or exclusive? Pick one convention and use it everywhere. I use half-open ranges: the start is included and the end is not.&lt;/p&gt;

&lt;p&gt;That makes adjacent bookings legal without special cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;09:00 &amp;lt;= appointment &amp;lt; 10:00
10:00 &amp;lt;= next appointment &amp;lt; 11:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generate candidates, then reject them
&lt;/h2&gt;

&lt;p&gt;I had better results by generating possible start times first and passing each one through the rules.&lt;/p&gt;

&lt;p&gt;For example, a staff member works from 09:00 to 17:00 and the booking interval is 30 minutes. Generate 09:00, 09:30, 10:00 and so on. Then reject candidates that fail a constraint.&lt;/p&gt;

&lt;p&gt;This is easier to reason about than trying to build one enormous database query that accounts for every rule at once. It also makes tests readable:&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;slotsFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-09-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;09:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// time off&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;slotsFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-09-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;11:30&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// available&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;slotsFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-09-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;16:30&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// runs past closing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last case catches an easy mistake. A 60-minute service cannot start at 16:30 just because the start time falls within working hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time zones are a display concern and a business rule
&lt;/h2&gt;

&lt;p&gt;Store timestamps in UTC, but do not pretend that solves time zones.&lt;/p&gt;

&lt;p&gt;The business defines availability in its own local time. A customer may view that availability from somewhere else. Daylight-saving changes mean “every Monday at 09:00” cannot safely be represented as “add seven lots of 24 hours”.&lt;/p&gt;

&lt;p&gt;The process I use is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Interpret working hours in the business time zone.&lt;/li&gt;
&lt;li&gt;Build the local date and time for the requested day.&lt;/li&gt;
&lt;li&gt;Convert candidate timestamps to UTC for comparisons and storage.&lt;/li&gt;
&lt;li&gt;Display them in the correct customer or business context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DST transition days deserve explicit tests. They are rare enough to be forgotten and common enough to break production calendars twice a year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preventing double bookings requires an atomic write
&lt;/h2&gt;

&lt;p&gt;Removing occupied times from the page is only the first defence.&lt;/p&gt;

&lt;p&gt;Two customers can load the same available slot, wait, and submit within milliseconds of each other. Both browsers are telling the truth based on the data they received.&lt;/p&gt;

&lt;p&gt;The server must check availability again while creating the booking. That check and insert need to happen atomically, using a transaction, lock or database constraint appropriate to the schema.&lt;/p&gt;

&lt;p&gt;The important rule is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The availability shown in the browser is helpful. The database is authoritative.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also use an idempotency key around booking creation. If a customer double-clicks or a request is retried, the same intent should not create two appointments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Payment status is not booking status
&lt;/h2&gt;

&lt;p&gt;A paid booking can be confirmed, pending, cancelled or refunded. A confirmed booking can be free or paid later.&lt;/p&gt;

&lt;p&gt;Combining these into one status field creates awkward states surprisingly quickly. I keep them separate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;booking_status: pending | confirmed | cancelled
payment_status: not_required | pending | paid | refunded | failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes webhook handling much less fragile and keeps the diary understandable when a payment provider is slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The boring cases are the real product
&lt;/h2&gt;

&lt;p&gt;The happy path makes a good screenshot. The product is everything around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a staff member takes the afternoon off&lt;/li&gt;
&lt;li&gt;a service needs a longer buffer&lt;/li&gt;
&lt;li&gt;a customer retries payment&lt;/li&gt;
&lt;li&gt;the clocks change&lt;/li&gt;
&lt;li&gt;two people choose the same time&lt;/li&gt;
&lt;li&gt;an appointment is moved rather than cancelled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why booking software is a good engineering exercise. The interface can remain simple only because the underlying rules are precise.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://www.open-slot.com/" rel="noopener noreferrer"&gt;OpenSlot&lt;/a&gt; around that idea: customers should see a clear choice of useful times, while the business keeps control of the rules behind them.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>architecture</category>
      <category>saas</category>
    </item>
    <item>
      <title>I Built a Simple Solana Wallet Export Tool Because Existing Ones Were Frustrating</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Thu, 21 May 2026 17:32:40 +0000</pubDate>
      <link>https://dev.to/graham23s/i-built-a-simple-solana-wallet-export-tool-because-existing-ones-were-frustrating-5hmd</link>
      <guid>https://dev.to/graham23s/i-built-a-simple-solana-wallet-export-tool-because-existing-ones-were-frustrating-5hmd</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Simple Tool to Export Phantom Wallet Transactions Without Coding
&lt;/h1&gt;

&lt;p&gt;If you’ve ever tried exporting transaction history from a Solana wallet, you’ve probably discovered two things pretty quickly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Most wallets don’t make it easy&lt;/li&gt;
&lt;li&gt;Crypto tax tools can get expensive fast&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That frustration is exactly why I built Export My Wallet.&lt;/p&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Paste a wallet address, export the transactions, and move on with your life.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No account creation. No complicated setup. No syncing exchanges for 45 minutes only to discover half the transactions are missing.&lt;/p&gt;

&lt;p&gt;Just a straightforward export tool for Solana wallets.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem I Kept Running Into
&lt;/h2&gt;

&lt;p&gt;I work on Solana projects regularly, and I kept needing transaction exports for things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tax calculations&lt;/li&gt;
&lt;li&gt;Tracking token launches&lt;/li&gt;
&lt;li&gt;Checking wallet activity&lt;/li&gt;
&lt;li&gt;Looking back through old trades&lt;/li&gt;
&lt;li&gt;Auditing transfers between wallets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The existing options were either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;overly complicated,&lt;/li&gt;
&lt;li&gt;painfully slow,&lt;/li&gt;
&lt;li&gt;or locked behind expensive subscriptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some platforms also tried to become your entire portfolio tracker when all you actually wanted was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Give me my transactions in a usable format.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I decided to build a lightweight alternative.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Tool Does
&lt;/h2&gt;

&lt;p&gt;With &lt;a href="https://www.exportmywallet.com" rel="noopener noreferrer"&gt;https://www.exportmywallet.com&lt;/a&gt;, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Export Solana wallet transactions&lt;/li&gt;
&lt;li&gt;Download CSV files&lt;/li&gt;
&lt;li&gt;View transaction history quickly&lt;/li&gt;
&lt;li&gt;Check token transfers&lt;/li&gt;
&lt;li&gt;Pull data for accounting or tax software&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It works with wallets like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Phantom&lt;/li&gt;
&lt;li&gt;Solflare&lt;/li&gt;
&lt;li&gt;Backpack&lt;/li&gt;
&lt;li&gt;and any public Solana address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t even need to connect your wallet if you don’t want to. You can simply paste the address.&lt;/p&gt;

&lt;p&gt;That was important to me.&lt;/p&gt;

&lt;p&gt;A lot of users are understandably cautious about connecting wallets to random websites. Public-address lookup avoids that entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Thing I Wanted to Avoid
&lt;/h2&gt;

&lt;p&gt;I didn’t want the site to feel like “crypto SaaS bingo”.&lt;/p&gt;

&lt;p&gt;You know the type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;giant dashboards,&lt;/li&gt;
&lt;li&gt;ten upsells,&lt;/li&gt;
&lt;li&gt;dark patterns everywhere,&lt;/li&gt;
&lt;li&gt;AI-generated marketing copy talking about “revolutionising finance”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I just wanted a utility that solved a problem cleanly.&lt;/p&gt;

&lt;p&gt;Fast input. Fast export. Minimal friction.&lt;/p&gt;

&lt;p&gt;Sometimes boring software is the best software.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Challenges
&lt;/h2&gt;

&lt;p&gt;Solana transaction history can get messy surprisingly quickly.&lt;/p&gt;

&lt;p&gt;A few things that made development interesting:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pagination and RPC limits
&lt;/h3&gt;

&lt;p&gt;Large wallets can have thousands of transactions. Pulling historical data efficiently without hammering RPC endpoints took a fair bit of optimisation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token metadata
&lt;/h3&gt;

&lt;p&gt;Not every token behaves nicely. Some older tokens have incomplete metadata, weird decimals, or broken symbols.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wallet parsing
&lt;/h3&gt;

&lt;p&gt;Simple SOL transfers are easy.&lt;/p&gt;

&lt;p&gt;DeFi interactions, NFT movements, swaps, and token account changes are not.&lt;/p&gt;

&lt;p&gt;Especially when users expect a clean CSV at the end.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Surprised Me Most
&lt;/h2&gt;

&lt;p&gt;Honestly?&lt;/p&gt;

&lt;p&gt;How many people just want simpler crypto tools.&lt;/p&gt;

&lt;p&gt;Not everyone wants advanced analytics or trading terminals.&lt;/p&gt;

&lt;p&gt;A lot of users simply want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clarity,&lt;/li&gt;
&lt;li&gt;exports,&lt;/li&gt;
&lt;li&gt;transparency,&lt;/li&gt;
&lt;li&gt;and tools that don’t feel hostile to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s probably the biggest thing I’ve learned building in crypto so far.&lt;/p&gt;




&lt;h2&gt;
  
  
  Future Plans
&lt;/h2&gt;

&lt;p&gt;A few things I’m working on next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better transaction categorisation&lt;/li&gt;
&lt;li&gt;Multi-chain exports&lt;/li&gt;
&lt;li&gt;Cleaner tax-ready formatting&lt;/li&gt;
&lt;li&gt;Faster large-wallet processing&lt;/li&gt;
&lt;li&gt;More export formats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m also experimenting with other lightweight crypto utilities alongside this project.&lt;/p&gt;




&lt;h2&gt;
  
  
  To Round This Up ...
&lt;/h2&gt;

&lt;p&gt;Crypto tooling still has a usability problem.&lt;/p&gt;

&lt;p&gt;There are amazing protocols and ecosystems underneath it all, but basic tasks can still feel harder than they should.&lt;/p&gt;

&lt;p&gt;I’m hoping this tool helps make one small part of that experience easier.&lt;/p&gt;

&lt;p&gt;If you want to try it, the site is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.exportmywallet.com/" rel="noopener noreferrer"&gt;https://www.exportmywallet.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cryptocurrency</category>
      <category>buildinpublic</category>
      <category>programming</category>
    </item>
    <item>
      <title>Create a Solana Token in 2 Minutes (No Code, No Setup, No Headache)</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Sat, 18 Apr 2026 20:40:13 +0000</pubDate>
      <link>https://dev.to/graham23s/create-a-solana-token-in-2-minutes-no-code-no-setup-no-headache-50hh</link>
      <guid>https://dev.to/graham23s/create-a-solana-token-in-2-minutes-no-code-no-setup-no-headache-50hh</guid>
      <description>&lt;p&gt;If you’ve ever tried to create a token on Solana, you’ll know how it usually goes…&lt;/p&gt;

&lt;p&gt;You start with a simple idea.&lt;br&gt;&lt;br&gt;
Then suddenly you’re installing tools, reading docs, and staring at a terminal wondering what just broke.&lt;/p&gt;

&lt;p&gt;Most guides assume you’re a developer. If you’re not, it’s a painful way to spend an afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Most people hit the same walls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to install and configure multiple tools
&lt;/li&gt;
&lt;li&gt;Token creation involves command line steps
&lt;/li&gt;
&lt;li&gt;One small mistake = confusing errors
&lt;/li&gt;
&lt;li&gt;It takes way longer than it should
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For something that should take minutes, it ends up feeling like a mini project.&lt;/p&gt;

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

&lt;p&gt;So I built something simpler:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.solana-token-creator.com" rel="noopener noreferrer"&gt;https://www.solana-token-creator.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A tool that lets you create a Solana token in minutes, without writing any code.&lt;/p&gt;

&lt;p&gt;You just:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect your wallet
&lt;/li&gt;
&lt;li&gt;Enter your token details
&lt;/li&gt;
&lt;li&gt;Confirm the transaction
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example
&lt;/h2&gt;

&lt;p&gt;Let’s say you want to test an idea for a token called &lt;strong&gt;TESTCOIN&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Normally you’d:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the Solana CLI
&lt;/li&gt;
&lt;li&gt;Create a mint
&lt;/li&gt;
&lt;li&gt;Set decimals
&lt;/li&gt;
&lt;li&gt;Mint supply
&lt;/li&gt;
&lt;li&gt;Handle metadata separately
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this, you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the site
&lt;/li&gt;
&lt;li&gt;Enter the name, supply, decimals
&lt;/li&gt;
&lt;li&gt;Click create
&lt;/li&gt;
&lt;li&gt;Approve in your wallet
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it’s done.&lt;/p&gt;

&lt;p&gt;No setup. No messing about.&lt;/p&gt;

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

&lt;p&gt;The tool handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SPL token creation
&lt;/li&gt;
&lt;li&gt;Supply + decimal configuration
&lt;/li&gt;
&lt;li&gt;Minting directly to your wallet
&lt;/li&gt;
&lt;li&gt;Basic token setup
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s built to do one thing well.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you’d actually use this
&lt;/h2&gt;

&lt;p&gt;You’ll likely use something like this if you’re:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launching a meme coin
&lt;/li&gt;
&lt;li&gt;Testing a token idea
&lt;/li&gt;
&lt;li&gt;Building a small Web3 project
&lt;/li&gt;
&lt;li&gt;Learning how Solana tokens work
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or just experimenting without committing to a full dev setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn’t do (important)
&lt;/h2&gt;

&lt;p&gt;This won’t make your token successful.&lt;/p&gt;

&lt;p&gt;It doesn’t:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add liquidity
&lt;/li&gt;
&lt;li&gt;Get you holders
&lt;/li&gt;
&lt;li&gt;Market your project
&lt;/li&gt;
&lt;li&gt;Build trust
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Creating the token is the easy part. Everything after that is where things get interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this approach
&lt;/h2&gt;

&lt;p&gt;I didn’t want another bloated Web3 tool.&lt;/p&gt;

&lt;p&gt;The goal was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast
&lt;/li&gt;
&lt;li&gt;Simple
&lt;/li&gt;
&lt;li&gt;No coding required
&lt;/li&gt;
&lt;li&gt;No unnecessary steps
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just something that works when you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback welcome
&lt;/h2&gt;

&lt;p&gt;If you’ve tried creating tokens before and hit issues, I’d be interested to hear what slowed you down.&lt;/p&gt;

&lt;p&gt;Also open to ideas for improvements that would actually make this more useful.&lt;/p&gt;

</description>
      <category>solana</category>
      <category>web3</category>
      <category>cryptocurrency</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Exporting Solana Wallet Transactions to CSV (Without the Headache)</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Sat, 18 Apr 2026 20:30:59 +0000</pubDate>
      <link>https://dev.to/graham23s/exporting-solana-wallet-transactions-to-csv-without-the-headache-2430</link>
      <guid>https://dev.to/graham23s/exporting-solana-wallet-transactions-to-csv-without-the-headache-2430</guid>
      <description>&lt;h1&gt;
  
  
  Exporting Solana Wallet Transactions to CSV (Without the Headache)
&lt;/h1&gt;

&lt;p&gt;If you’ve ever tried to export transaction data from a Solana wallet, you’ll know it’s not exactly straightforward.&lt;/p&gt;

&lt;p&gt;Explorers like Solscan are great for browsing, but not so great when you actually need clean, structured data you can use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Most people hit the same issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No simple way to export full transaction history
&lt;/li&gt;
&lt;li&gt;Data is hard to work with (especially for taxes or analysis)
&lt;/li&gt;
&lt;li&gt;Existing tools are either overcomplicated or expensive
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you just want a clean CSV of your wallet activity, it ends up taking way longer than it should.&lt;/p&gt;

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

&lt;p&gt;I built a simple tool called &lt;strong&gt;Export My Wallet&lt;/strong&gt; that does one thing well:&lt;/p&gt;

&lt;p&gt;👉 Converts any Solana wallet into a clean CSV in seconds&lt;/p&gt;

&lt;p&gt;You just:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter a wallet address
&lt;/li&gt;
&lt;li&gt;Wait a few seconds
&lt;/li&gt;
&lt;li&gt;Download the CSV
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

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

&lt;p&gt;The export covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full transaction history
&lt;/li&gt;
&lt;li&gt;Swaps and transfers
&lt;/li&gt;
&lt;li&gt;Token activity
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s designed to be immediately usable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tax reporting
&lt;/li&gt;
&lt;li&gt;Tracking activity
&lt;/li&gt;
&lt;li&gt;Portfolio analysis
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When you actually need this
&lt;/h2&gt;

&lt;p&gt;You’ll likely need a CSV export if you’re:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing crypto tax reports
&lt;/li&gt;
&lt;li&gt;Tracking wallet activity over time
&lt;/li&gt;
&lt;li&gt;Analysing trading behaviour
&lt;/li&gt;
&lt;li&gt;Keeping records for accounting
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most tools don’t make this easy, especially on Solana.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this approach
&lt;/h2&gt;

&lt;p&gt;I didn’t want to build another “all-in-one crypto dashboard”.&lt;/p&gt;

&lt;p&gt;The goal was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast
&lt;/li&gt;
&lt;li&gt;Simple
&lt;/li&gt;
&lt;li&gt;No wallet connection required
&lt;/li&gt;
&lt;li&gt;No unnecessary complexity
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just a tool that solves a very specific problem well.&lt;/p&gt;

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

&lt;p&gt;👉 &lt;a href="https://www.exportmywallet.com" rel="noopener noreferrer"&gt;https://www.exportmywallet.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback welcome
&lt;/h2&gt;

&lt;p&gt;If you’ve run into similar issues exporting wallet data, or you’ve got ideas for improvements (filters, date ranges, token-specific exports), I’d love to hear them.&lt;/p&gt;

</description>
      <category>solana</category>
      <category>web3</category>
      <category>cryptocurrency</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I built a Web3 tools directory because everything is scattered</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Tue, 17 Mar 2026 17:57:11 +0000</pubDate>
      <link>https://dev.to/graham23s/i-built-a-web3-tools-directory-because-everything-is-scattered-4n3a</link>
      <guid>https://dev.to/graham23s/i-built-a-web3-tools-directory-because-everything-is-scattered-4n3a</guid>
      <description>&lt;h1&gt;
  
  
  I built a Web3 tools directory because everything is scattered
&lt;/h1&gt;

&lt;p&gt;Creating anything in Web3 is weirdly harder than it should be.&lt;/p&gt;

&lt;p&gt;Not because of the tech itself, but because everything you need is scattered everywhere.&lt;/p&gt;

&lt;p&gt;You find one tool on Twitter, another buried in a GitHub repo, then a random blog post from 2021 that might still be relevant… or might not.&lt;/p&gt;

&lt;p&gt;It slows everything down.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;If you're building in Web3, you've probably experienced this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need a tool for something specific
&lt;/li&gt;
&lt;li&gt;You search Google and get outdated results
&lt;/li&gt;
&lt;li&gt;You check Twitter and find threads with half-broken links
&lt;/li&gt;
&lt;li&gt;You dig through GitHub repos with little context
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s no single place that feels reliable or complete.&lt;/p&gt;

&lt;p&gt;Everything is fragmented.&lt;/p&gt;

&lt;p&gt;And when you're trying to build something quickly, that fragmentation becomes friction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;In most industries, tools are easy to find.&lt;/p&gt;

&lt;p&gt;You’ve got directories, marketplaces, comparison sites.&lt;/p&gt;

&lt;p&gt;In Web3, it’s still messy.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More time searching
&lt;/li&gt;
&lt;li&gt;Less time building
&lt;/li&gt;
&lt;li&gt;More duplication of effort
&lt;/li&gt;
&lt;li&gt;Missed tools that could actually help
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It shouldn’t be like that.&lt;/p&gt;




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

&lt;p&gt;So I built &lt;strong&gt;Web3ToolLaunch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.web3toollaunch.com/" rel="noopener noreferrer"&gt;https://www.web3toollaunch.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s a simple directory focused on one thing:&lt;/p&gt;

&lt;p&gt;Making Web3 tools easier to discover.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you can do with it
&lt;/h2&gt;

&lt;p&gt;Right now you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browse tools by category
&lt;/li&gt;
&lt;li&gt;Explore areas like DeFi, AI crypto, NFT and infrastructure
&lt;/li&gt;
&lt;li&gt;Discover tools you probably wouldn’t have found otherwise
&lt;/li&gt;
&lt;li&gt;Submit your own tool
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No accounts required, no friction.&lt;/p&gt;

&lt;p&gt;Just a clean list of tools that are actually useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it’s different
&lt;/h2&gt;

&lt;p&gt;I’m not trying to build another bloated marketplace.&lt;/p&gt;

&lt;p&gt;The focus is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity
&lt;/li&gt;
&lt;li&gt;Discoverability
&lt;/li&gt;
&lt;li&gt;Clean structure
&lt;/li&gt;
&lt;li&gt;Useful categories
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over time, the goal is to make this a go-to place when you're starting a new Web3 project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Early challenges
&lt;/h2&gt;

&lt;p&gt;A few things became obvious straight away:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Seeding content
&lt;/h3&gt;

&lt;p&gt;A directory is only useful if it has content.&lt;/p&gt;

&lt;p&gt;So the early phase is manually adding tools and making sure the categories make sense.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Quality vs quantity
&lt;/h3&gt;

&lt;p&gt;It’s tempting to add everything.&lt;/p&gt;

&lt;p&gt;But a directory full of low-quality tools is worse than a smaller, curated one.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Getting submissions
&lt;/h3&gt;

&lt;p&gt;The real growth comes when other founders start submitting their tools.&lt;/p&gt;

&lt;p&gt;That’s the next big step.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;I’m planning to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expand categories (more specific niches)&lt;/li&gt;
&lt;li&gt;Add better filtering and sorting&lt;/li&gt;
&lt;li&gt;Highlight featured tools&lt;/li&gt;
&lt;li&gt;Improve SEO pages for each category&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Long term, I want this to become a proper resource for developers and founders building in Web3.&lt;/p&gt;




&lt;h2&gt;
  
  
  And Finally ...
&lt;/h2&gt;

&lt;p&gt;Web3 has no shortage of tools.&lt;/p&gt;

&lt;p&gt;What it lacks is organisation.&lt;/p&gt;

&lt;p&gt;That’s what I’m trying to fix.&lt;/p&gt;

&lt;p&gt;If it saves someone a bit of time, it’s already worth it.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>cryptocurrency</category>
      <category>startup</category>
      <category>devtools</category>
    </item>
    <item>
      <title>How to Create a Solana NFT Without Writing Any Code</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Sat, 14 Mar 2026 08:20:57 +0000</pubDate>
      <link>https://dev.to/graham23s/how-to-create-a-solana-nft-without-writing-any-code-1gdi</link>
      <guid>https://dev.to/graham23s/how-to-create-a-solana-nft-without-writing-any-code-1gdi</guid>
      <description>&lt;h2&gt;
  
  
  Creating a Solana NFT Without Writing Any Code
&lt;/h2&gt;

&lt;p&gt;If you've ever tried minting an NFT on Solana from scratch, you'll know the process can feel a bit technical at first. Between generating metadata, uploading files to decentralized storage, and preparing the mint transaction, there are quite a few moving parts.&lt;/p&gt;

&lt;p&gt;The good news is that you don't necessarily need to write scripts or interact with CLI tools anymore. There are now simpler ways to create NFTs on Solana that handle the technical parts for you.&lt;/p&gt;

&lt;p&gt;This guide explains how Solana NFTs work and how you can create one without needing to write any code.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Makes a Solana NFT Different?
&lt;/h3&gt;

&lt;p&gt;A Solana NFT is simply a token on the Solana blockchain that represents a unique digital item. That item might be artwork, a collectible, music, or even access to a community.&lt;/p&gt;

&lt;p&gt;Unlike regular tokens, NFTs contain metadata describing the asset. This metadata includes information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the NFT name
&lt;/li&gt;
&lt;li&gt;a description
&lt;/li&gt;
&lt;li&gt;the image or media file
&lt;/li&gt;
&lt;li&gt;optional attributes or traits
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The metadata is usually stored outside the blockchain on decentralized storage such as IPFS or Arweave. The NFT token itself simply references that metadata.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example NFT Metadata
&lt;/h3&gt;

&lt;p&gt;A typical Solana NFT metadata file looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example NFT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"symbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NFT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Solana NFT metadata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/image.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"trait_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Background"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blue"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"trait_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eyes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Laser"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the NFT is minted, the token points to this metadata file. Marketplaces then read the metadata and display the NFT image, traits, and description.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Traditional Minting Workflow
&lt;/h3&gt;

&lt;p&gt;Developers who mint NFTs manually usually follow a process like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the artwork or digital asset
&lt;/li&gt;
&lt;li&gt;Write the metadata JSON file
&lt;/li&gt;
&lt;li&gt;Upload files to IPFS or Arweave
&lt;/li&gt;
&lt;li&gt;Use Solana tools to mint the token
&lt;/li&gt;
&lt;li&gt;Verify the NFT on a marketplace
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For developers this process is manageable, but for creators or beginners it can feel unnecessarily complicated.&lt;/p&gt;




&lt;h3&gt;
  
  
  A Simpler Way to Create Solana NFTs
&lt;/h3&gt;

&lt;p&gt;These days many people use web-based tools that automate most of the process.&lt;/p&gt;

&lt;p&gt;Instead of preparing metadata and scripts yourself, the tool generates the metadata, uploads files, and prepares the mint transaction automatically.&lt;/p&gt;

&lt;p&gt;For example, this tool allows you to create and mint NFTs directly from your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.solana-nft-creator.com/create-nft/" rel="noopener noreferrer"&gt;Solana NFT creator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea is straightforward: you upload your artwork, enter the NFT details, and the platform handles the technical steps behind the scenes.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Many NFT Projects Use Solana
&lt;/h3&gt;

&lt;p&gt;Solana has become popular for NFT projects for a few practical reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transaction fees are extremely low
&lt;/li&gt;
&lt;li&gt;confirmation times are very fast
&lt;/li&gt;
&lt;li&gt;the ecosystem of NFT marketplaces is growing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because minting costs are so small compared to other blockchains, Solana is often used for experimental collections or new creator projects.&lt;/p&gt;




&lt;h3&gt;
  
  
  Where Solana NFTs Are Sold
&lt;/h3&gt;

&lt;p&gt;Once minted, Solana NFTs can be listed on marketplaces such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Magic Eden
&lt;/li&gt;
&lt;li&gt;Tensor
&lt;/li&gt;
&lt;li&gt;Solanart
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These platforms allow creators to sell NFTs and collect royalties from secondary sales.&lt;/p&gt;




&lt;h3&gt;
  
  
  To Wrap Things Up ...
&lt;/h3&gt;

&lt;p&gt;Creating NFTs on Solana used to involve several technical steps, especially around metadata and minting scripts.&lt;/p&gt;

&lt;p&gt;Today, tools exist that simplify the workflow so creators can focus more on the artwork or project itself rather than the infrastructure.&lt;/p&gt;

&lt;p&gt;If you're curious about the Solana NFT ecosystem, the easiest way to understand it is simply to try minting one and see how the process works.&lt;/p&gt;

</description>
      <category>solana</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>nft</category>
    </item>
    <item>
      <title>How I Create Solana Tokens Without Writing Any Rust</title>
      <dc:creator>Graham McCann</dc:creator>
      <pubDate>Thu, 05 Feb 2026 13:13:05 +0000</pubDate>
      <link>https://dev.to/graham23s/how-i-create-solana-tokens-without-writing-any-rust-21ai</link>
      <guid>https://dev.to/graham23s/how-i-create-solana-tokens-without-writing-any-rust-21ai</guid>
      <description>&lt;h2&gt;
  
  
  Creating a Solana Token Without Wrestling With the Tooling
&lt;/h2&gt;

&lt;p&gt;Creating a Solana token sounds simple until you actually try it.&lt;/p&gt;

&lt;p&gt;You read the docs, install half the internet, argue with Rust versions, get lost in SPL token flags, and somehow still end up wondering if you’ve accidentally given mint authority to the void.&lt;/p&gt;

&lt;p&gt;I kept seeing the same questions pop up in Solana and Web3 dev spaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I mint a Solana token quickly?&lt;/li&gt;
&lt;li&gt;Do I need to write Rust for this?&lt;/li&gt;
&lt;li&gt;How do I handle metadata properly?&lt;/li&gt;
&lt;li&gt;How do I avoid messing up supply or authority?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built a small tool that does one thing well: it lets you create a Solana token cleanly, without touching Rust or CLI tooling.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Flow Is Simple
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Connect your wallet
&lt;/li&gt;
&lt;li&gt;Set the token name, symbol, supply and decimals
&lt;/li&gt;
&lt;li&gt;Add metadata if you want it
&lt;/li&gt;
&lt;li&gt;Mint the token
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No test scripts.&lt;br&gt;&lt;br&gt;
No local builds.&lt;br&gt;&lt;br&gt;
No copy-pasting commands you don’t fully trust.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Happens Under the Hood
&lt;/h3&gt;

&lt;p&gt;Under the hood it still follows standard Solana token behaviour.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mint authority is explicit
&lt;/li&gt;
&lt;li&gt;Freeze authority is visible
&lt;/li&gt;
&lt;li&gt;Supply configuration is clear
&lt;/li&gt;
&lt;li&gt;Metadata is handled properly
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing hidden, nothing magical. Just a cleaner interface for the standard token process.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why I Built It
&lt;/h3&gt;

&lt;p&gt;Originally I built the tool for my own launches.&lt;/p&gt;

&lt;p&gt;After a while a few other developers started using it too, mostly for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;quick experiments
&lt;/li&gt;
&lt;li&gt;MVP projects
&lt;/li&gt;
&lt;li&gt;early-stage token ideas
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes you just want to spin up a token and move on to the interesting part of the project.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Tool
&lt;/h3&gt;

&lt;p&gt;If you're curious, you can try it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.soltokenlaunch.com" rel="noopener noreferrer"&gt;https://www.soltokenlaunch.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's not meant to replace custom Solana programs or serious on-chain development. It simply removes the friction when you want to create a token quickly without building the entire infrastructure stack first.&lt;/p&gt;




&lt;h3&gt;
  
  
  Curious About Other Workflows
&lt;/h3&gt;

&lt;p&gt;If you're already deep into Solana development, I’d be genuinely interested to hear how you handle token creation in your own workflow.&lt;/p&gt;

&lt;p&gt;Do you rely on CLI tooling, custom scripts, or something else?&lt;/p&gt;




&lt;h3&gt;
  
  
  Related Reading
&lt;/h3&gt;

&lt;p&gt;I also wrote a broader (and less technical) breakdown of why browser-based token creation is changing how people onboard into Solana here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@GrahamMcC/creating-a-solana-token-is-easier-than-it-used-to-be-heres-why-that-matters-968361784f70" rel="noopener noreferrer"&gt;Creating a Solana token is easier than it used to be — here's why that matters&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>showdev</category>
      <category>tooling</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
