DEV Community

Cover image for Get Your Free got-a.page Subdomain: A Step-by-Step Guide
Dhanush N
Dhanush N

Posted on

Get Your Free got-a.page Subdomain: A Step-by-Step Guide

I recently bought the domain got-a.page and turned it into a free, community-run subdomain service. Anyone can claim a name like yourname.got-a.page with one small JSON file and one pull request. No hosting bill, no registrar account, no ads, no tracking.

This guide walks through the whole thing: picking a name, choosing a mode, opening the PR, and what to expect after it merges.

What is got-a.page?

got-a.page gives you a free subdomain for your profile, product, project or community. Claims live in a public GitHub repo, one JSON file per page, and a maintainer merges them. There are two ways to use your name:

Instant mode - no website? We host the page for you.
Fill in your name, a tagline and your links, and a fast, accessible page is rendered at yourname.got-a.page. Light and dark mode included, in one of six themes: sunrise, lagoon, forest, plum, slate, ember. Person and product pages are supported today.

{
  "mode": "instant",
  "owner": { "github": "yourusername" },
  "page": {
    "type": "person",
    "title": "Your Name",
    "tagline": "What you're about, in one line",
    "avatar": "https://github.com/yourusername.png",
    "theme": "sunrise",
    "links": [{ "label": "GitHub", "url": "https://github.com/yourusername" }],
    "sections": [{ "heading": "About", "text": "A few sentences about you." }]
  }
}
Enter fullscreen mode Exit fullscreen mode

Point mode - already hosting somewhere?
Point your name at GitHub Pages, Vercel, Netlify, Cloudflare Pages, or anywhere that gives you a hostname or IP. CNAME, A, AAAA and TXT records are supported. One DNS rule to know: a CNAME can't be combined with other record types on the same name.

{
  "mode": "point",
  "owner": { "github": "yourusername" },
  "purpose": "My portfolio",
  "records": { "CNAME": "yourusername.github.io" }
}
Enter fullscreen mode Exit fullscreen mode

You can switch modes later by editing your file with a new PR. And yes, it's really free: the domain is paid for years ahead and everything else runs on free tiers.

Before you start

  • A GitHub account. Claims are tied to it: owner.github must match the PR author, and only you (or a maintainer) can edit or remove your page later.
  • A name that's 2-40 characters of lowercase letters, numbers and hyphens.
  • Up to 2 pages per GitHub account while we're young.
  • Everything in the repo is public, forever. Don't put private data in your file.

Step 1: Open the guided claim form

Go to got-a.page/claim. The form writes the JSON for you, so you never touch raw JSON. There's a name checker on the homepage if you want to see whether your name is free first.

Step 2: Answer a few questions

Enter your page name, pick instant or point mode, and fill in the fields. Instant mode asks for your title, tagline, theme and links. Point mode asks for the DNS target your host recommends.

Step 3: Propose it on GitHub

The button at the end opens the claim repo on GitHub with your file prefilled. GitHub will ask you to fork (one click), then you choose "Propose changes" and open the pull request.

Automated validation checks review your file. Follow the check results on your PR - fork PRs don't get automatic bot comments, so the checks are where the feedback lives. A maintainer merges when it looks good.

Never made a pull request before? The repo's contributing guide walks you through every click. It's a kind place for your first one.

Step 4 (point mode only): connect your host before merge

This is the step people miss. A merged claim creates DNS records, but it does not add the domain to your hosting account. Add yourname.got-a.page on your host before the claim is merged:

  • GitHub Pages: your website repo > Settings > Pages > Custom domain, enter yourname.got-a.page, Save. Use "records": { "CNAME": "yourusername.github.io" } in your claim.
  • Vercel: your project > Settings > Domains > Add Domain. Copy the project-specific CNAME target Vercel gives you into your claim.
  • Netlify: Domain management > Add a domain you already own. Keep external DNS and copy the recommended target (usually your-site.netlify.app).
  • Cloudflare Pages: your Pages project > Custom domains > Set up a domain. Use your your-site.pages.dev target.

The docs at got-a.page/docs have the full per-host walkthrough.

What to expect after your PR merges

Instant mode: your page goes live within a few minutes. Until the index republishes, your address may still show the "unclaimed" page - that's normal, give it a few minutes and hard-refresh.

Point mode: DNS publishes first, then your host verifies the domain and issues its HTTPS certificate. Browsers will show a privacy or certificate error for your address during that window. That's expected - minutes to hours, occasionally longer. GitHub documents up to 24 hours for Enforce HTTPS to become available; turn it on once you can.

One HTTPS note: .page is on the HSTS preload list, so browsers force HTTPS on every got-a.page address. Instant pages are always secure (handled for you), and point-mode targets must serve valid HTTPS or browsers will refuse to load them. All the hosts above do that automatically once the custom domain is added.

"Is it broken?" - troubleshooting

What you see What's going on
Certificate/privacy error right after merge (point mode) Normal. Your host's certificate isn't ready yet. Wait, then enable Enforce HTTPS when offered.
Your old yourname.github.io shows the same error Expected. GitHub Pages redirects the old address to your custom domain as soon as you save it, so both show the error during the wait and both recover together.
Your address still says "unclaimed" (instant mode) The index hasn't republished yet. A few minutes, then hard-refresh.
Page loads but looks unstyled Your site is loading CSS/JS from the old address or over http://. Use relative asset URLs or update your static site generator's base URL setting.
Still stuck after a day Open an issue in the claim repo with your page name and what you see. Real humans read them.

The rules, short version

  • Claim with your own GitHub account.
  • Your page is public. Everything in the repo is public.
  • No phishing, scams, malware, impersonation, illegal or adult content.
  • Some names are reserved (service addresses, brand names, and words that would make the place less welcoming).
  • See abuse? Email abuse@got-a.page.

Extras

Badges: once your page is live, grab an "I got a page" or "Launched on got-a.page" badge from got-a.page/badges - HTML and Markdown snippets, ready to paste into your README.

What's coming later: more page types (project, community and event templates), a Wall of Pages gallery, and email on your subdomain. None of that is live yet - I'm adding it in later phases, and everything above is what works today.

Wrap up

  1. Check your name on got-a.page
  2. Claim it at got-a.page/claim
  3. Open the PR, follow the checks, done

Claim repo: github.com/got-a-page/claim - MIT licensed, and issues and first PRs are welcome. If you claim a page, drop your new address in the comments. I'd love to see what you make of it.

Top comments (2)

Collapse
 
merbayerp profile image
Mustafa ERBAY •

Hey Dhanush! 👋😊

First of all, congratulations on launching got-a.page! I really like the idea of combining free subdomains, GitHub pull requests, and GitOps-based DNS management.

I was curious about the implementation, so I downloaded your claim repository and spent some time reviewing the validation logic, ownership checks, and DNS synchronization code.

I found a few things worth sharing. 🔍

🔴 1. IPv6 validation accepts malformed addresses

In scripts/src/lib/ips.ts, the current implementation is:

export function isValidIpv6(ip: string): boolean {
  return /^[0-9a-fA-F:]+$/.test(ip) && ip.includes(":");
}
Enter fullscreen mode Exit fullscreen mode

This checks the character set but doesn’t validate IPv6 syntax.

For example, a:b, ::::, and abcd: can pass this function despite being invalid IPv6 addresses.

I’d recommend using Node.js’s built-in net.isIP() instead:

import { isIP } from "node:net";
export function isValidIpv6(ip: string): boolean {
  return isIP(ip) === 6;
}
Enter fullscreen mode Exit fullscreen mode

This is directly verifiable from the source.

🟠 2. Git reference loading may fail to enumerate existing claims

In scripts/src/lib/store.ts, loadPagesAtRef() uses:

git ls-tree --name-only <ref> pages/
Enter fullscreen mode Exit fullscreen mode

Without -r, git ls-tree doesn’t recursively enumerate the JSON files inside pages/.

Since the following loop only processes paths ending in .json, existing claims may not be loaded as intended.

Additionally, Git errors are caught and converted into an empty map.

Because this function supplies historical claim data for PR comparisons, I’d recommend investigating its effect on ownership validation.

A safer starting point would be:

git ls-tree -r --name-only <ref> -- pages/
Enter fullscreen mode Exit fullscreen mode

I’d also distinguish a genuinely empty directory from a failed Git operation.

🔴 3. DNS synchronization has a potentially broad deletion boundary

In scripts/src/dns-sync.ts, the reconciliation logic includes:

for (const r of live) {
  if (r.managed && !matched.has(r.id)) {
    plan.remove.push(r);
  }
}
Enter fullscreen mode Exit fullscreen mode

This means any record classified as managed but absent from the desired state becomes a deletion candidate.

That approach can be valid for an exclusively managed DNS zone.

However, if multiple automation systems share the same zone or management marker, the deletion scope deserves additional protection.

I’d recommend explicitly verifying ownership and management scope before destructive operations.

To be clear, I haven’t demonstrated an unintended deletion against your live Cloudflare zone. This is an architectural risk identified through code inspection.

🟠 4. IP address classification could be more robust

The IPv4 and IPv6 restrictions currently rely on manually maintained regular expressions and prefix checks.

For example, the IPv4 exclusions don’t comprehensively cover all special-purpose address ranges, including 240.0.0.0/4.

Using standard IP parsing and an explicit address-classification policy would make this easier to maintain and test.

🟡 5. DNS reconciliation isn’t atomic

The synchronization process performs create, update, and delete operations sequentially.

If an API request fails halfway through, the zone may temporarily remain in a partially updated state.

I’d consider adding stronger failure reporting, post-apply verification, and recovery tests.

This isn’t necessarily a bug, but it’s important for operational reliability.

✅ What I liked

There are also several good engineering decisions here:

  • GitOps-based configuration and reviewable pull requests.
  • JSON Schema validation.
  • GitHub Actions dependencies pinned to commit SHAs.
  • Cloudflare credentials supplied through environment secrets.
  • Dry-run behavior before applying DNS changes.
  • A relatively clear separation between claim validation and DNS management.

These are sensible foundations for a community project.

My suggested priorities:

  1. Fix IPv6 syntax validation.
  2. Correct Git tree enumeration and verify ownership checks.
  3. Tighten the DNS deletion boundary.
  4. Expand IP classification tests.
  5. Add reconciliation failure and recovery tests.

One important limitation: my review covered the supplied claim repository, not the complete production infrastructure. I haven’t audited the Instant Mode Worker, live Cloudflare permissions, or the deployed GitHub branch protection settings.

So these are source-level findings and architectural recommendations, not claims that your production service has been compromised.

Overall, I appreciate the transparency and simplicity of the project. Making a useful service free and approachable while encouraging people to learn GitHub contributions is a great initiative.

I hope these findings are helpful. I’m sharing them constructively because I genuinely like what you’re building.

Keep up the good work, Dhanush! 🌱🔐

Collapse
 
dhanushnehru profile image
Dhanush N •

Thanks for the points

Feel free to add the suggested things as issues in the repository so it will be easy to track.