carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1{{define "app_new"}}{{template "top" .}}
2{{if .Flash}}<p class="banner">{{.Flash}}</p>{{end}}
3{{if .FlashErr}}<p class="banner error">{{.FlashErr}}</p>{{end}}
4<div class="pagehead">
5 <p class="eyebrow">Account · {{.Account.Name}}</p>
6 <h1>Create an app</h1>
7 <p class="lede">Claim a name here; ship a release to it from your terminal.</p>
8</div>
9<form class="signin" method="post" action="{{.Base}}/apps/new">
10 <input type="hidden" name="csrf" value="{{.CSRF}}">
11 <label class="visually-hidden" for="app-name">App name</label>
12 <input id="app-name" type="text" name="name" placeholder="my-app" autofocus
13 required pattern="[A-Za-z][A-Za-z0-9-]{0,31}" maxlength="32">{{with .RegionPicker}}
14 <label for="app-region">{{$.RegionCopy.PickerLabel}}</label>
15 <select id="app-region" name="region">
16 <option value="@auto" selected>{{.Auto}}</option>
17 {{range .Options}}<option value="{{.Value}}">{{.Label}}</option>{{end}}
18 </select>
19 <input type="hidden" name="tz" value="">
20 <p class="small">{{$.RegionCopy.PickerHelp}}</p>
21 {{if .Attribution}}<p class="small"><a href="{{.AttributionURL}}">{{.AttributionText}}</a></p>{{end}}
22 <script>
23 // Enhancement only: with JS off the server's IP-or-home guess stands.
24 // Fills the tz hint and relabels ONLY the @auto option; its value stays
25 // "@auto" so the server still knows the person did not choose.
26 (function () {
27 var f = document.currentScript.closest("form"), sel = f.elements.region, tz = "";
28 var label = {{printf $.RegionCopy.AutoOption "%PLACE%"}};
29 try { tz = Intl.DateTimeFormat().resolvedOptions().timeZone || ""; } catch (e) {}
30 f.elements.tz.value = tz;
31 if (!tz) return;
32 var body = new URLSearchParams({ csrf: f.elements.csrf.value, tz: tz });
33 fetch("{{$.Base}}/apps/new/region", { method: "POST", body: body, credentials: "same-origin" })
34 .then(function (r) { return r.ok ? r.json() : null; })
35 .then(function (g) {
36 if (!g || sel.value !== "@auto") return;
37 sel.options[0].text = label.replace("%PLACE%", g.name);
38 })
39 .catch(function () {});
40 })();
41 </script>{{end}}
42 <button type="submit">Create app</button>
43</form>
44<p class="small">Names are lowercase letters, digits, and dashes, starting with a letter — unique within this account, not across the platform.</p>
45{{template "bottom" .}}{{end}}
46