docs(11.2): reshape into the Alpha 0.1 landing page and split the newsletter into 11.3
This commit is contained in:
@@ -568,28 +568,50 @@ Plans:
|
||||
**Wave 7** *(gap closure, blocked on Wave 6 completion)*
|
||||
- [x] 11.1-07-PLAN.md — Checkers fail closed: AST fence discovery (nested and README src= refused, captions only on verified fences, Go-lexer aliases need src=), go test roots and go/build membership for src= targets, `go doc -c`, env/flag/go run/bin command forms; planted fixtures and unit tests for every hole
|
||||
|
||||
### Phase 11.2: Ready to share: summercms.io website and newsletter plugin (INSERTED)
|
||||
### Phase 11.2: summercms.io Alpha 0.1 landing page on SummerCMS (INSERTED)
|
||||
|
||||
**Goal:** summercms.io is ready to share publicly. A fresh Nuxt 4 website in English and Polish runs on a SummerCMS binary. Visitors subscribe for updates through the initial Go version of the Golem15 Newsletter plugin, which confirms each email by double opt-in. The Phase 11.1 docs are served at `/docs` and linked from the site.
|
||||
**Goal:** summercms.io replaces its "Under construction" page with the Alpha 0.1 landing page from the claude.ai/design handoff. The page is a Nuxt 4 static site, English only and i18n-ready, embedded in and served by a SummerCMS binary that also serves the Phase 11.1 docs at `/docs`. It deploys behind nginx with supervisor using documented steps. This is a quick phase of 2-3 plans; newsletter signup moved to Phase 11.3.
|
||||
**Requirements**: TBD
|
||||
**Depends on:** Phase 11.1
|
||||
**Repos:** four new repos under `git.golem15.com/golem15/`: (1) `sm-summercms-app`, the root app that builds the binary and wires the plugins; (2) `vue-summercms-app`, the Nuxt 4 site, held inside the root app; (3) `sm-summercms-plugin`, the site plugin that serves the embedded site at `/`, the docs at `/docs` and any site-specific data, the WinterCMS site-plugin pattern; (4) `sm-newsletter-plugin`, the reusable signup plugin. `summercms.go` changes only if the site needs a framework feature that is missing.
|
||||
**Repos:** three new repos under `git.golem15.com/golem15/`: (1) `sm-summercms-app`, the root app that builds the binary and wires the plugins; (2) `vue-summercms-app`, the Nuxt 4 site, held inside the root app; (3) `sm-summercms-plugin`, the site plugin that serves the embedded site at `/`, the docs at `/docs` and any site-specific data, the WinterCMS site-plugin pattern. `summercms.go` changes only if the site needs a framework feature that is missing.
|
||||
**Naming convention:** the same as OctoberCMS (`oc-`) and WinterCMS (`wn-`), with the `sm-` prefix: root app `sm-<name>-app`, Vue frontend `vue-<name>-app`, plugin `sm-<name>-plugin`, theme `sm-<name>-theme`. The Go package inside a plugin keeps its plain name (`newsletter`). The meta root `summercms.io` and the framework `summercms.go` keep their names. `fonoteka.go` becomes `sm-fonoteka-app`.
|
||||
**Port source:** Golem15.Newsletter, `github.com/golem15com/wn-newsletter-plugin`, checked out at `/media/nvme/dev/golem15/horoskopia.eu/plugins/golem15/newsletter`. The PHP plugin is work in progress. Its audience comes from registered users (it requires `Golem15.User`), and its only public routes are unsubscribe. It has no public subscriber model or signup widget, so this phase adds those in Go. The PHP original is not changed.
|
||||
**Design source:** `.planning/phases/11.2-ready-to-share-summercms-io-website-and-newsletter-plugin/design/` (handoff `README.md`, `SummerCMS Landing.dc.html`, `assets/sun-crop.png`). The design is high fidelity: colors, type, spacing and copy are final. The handoff supersedes 11.2-CONTEXT D-06 (English only for now), D-08, D-10 and D-11 (no signup, "Alpha 0.1 is out", Source links allowed).
|
||||
**Success Criteria** (what must be TRUE):
|
||||
|
||||
1. The newsletter plugin repo exists and ships an initial stub: a public signup endpoint (validated, honeypot and rate-limited, with required consent), double opt-in confirmation mail with a tokenized confirm link, a welcome mail, unsubscribe, and subscriber add, edit and delete in the admin SPA. Composing and sending newsletters is out of scope.
|
||||
2. The website repo exists and ships a prerendered English and Polish summercms.io landing page with a signup widget. The widget calls the plugin's API on the same origin and covers the pending, confirmed and error states.
|
||||
3. The Phase 11.1 docs are served at `summercms.io/docs`, the landing page links to them, and every link resolves.
|
||||
4. The site deploys as one binary with the Nuxt build and the docs embedded, with documented build and run steps.
|
||||
1. `nuxt generate` in `vue-summercms-app` produces the landing page matching the handoff: sticky header with scroll-spy, hero, the Why, Features, From WinterCMS and Get started sections, a terminal card with a working Copy button, and a footer. It is responsive down to phone width, and the section links hide at 720px or less.
|
||||
2. One `sm-summercms-app` binary embeds the Nuxt output and the Phase 11.1 docs build. It serves `/` and `/docs` with indexable responses (no admin `noindex`/CSP) and with cache headers: immutable for hashed assets, no-cache for HTML.
|
||||
3. Every link on the page resolves, including the eight feature-tile `/docs/...` links and the WinterCMS concept-map link. They are verified against the built docs, not assumed.
|
||||
4. A scripted build (`nuxt generate`, then `summer docs:build`, then `go build`) and a `DEPLOY.md` in the root app cover building, uploading, a supervisor program config, and an nginx site config (TLS, proxy to the binary, gzip). Following it on a clean server brings the site up.
|
||||
5. The new Go code has unit tests, delivered in the phase's last plan.
|
||||
|
||||
**Context:** `.planning/phases/11.2-ready-to-share-summercms-io-website-and-newsletter-plugin/11.2-CONTEXT.md`
|
||||
**Context:** `.planning/phases/11.2-ready-to-share-summercms-io-website-and-newsletter-plugin/11.2-CONTEXT.md` (D-01 to D-05, D-07, D-09 and D-12 still apply; see its supersession note)
|
||||
|
||||
**Plans:** 0 plans
|
||||
|
||||
Plans:
|
||||
- [ ] TBD (run /gsd-plan-phase 11.2 to break down)
|
||||
|
||||
### Phase 11.3: Newsletter plugin and signup on summercms.io (INSERTED)
|
||||
|
||||
**Goal:** Visitors to summercms.io subscribe for updates through the initial Go version of the Golem15 Newsletter plugin, which confirms each email by double opt-in. The signup widget is added to the Phase 11.2 landing page, and the site gains Polish alongside English.
|
||||
**Requirements**: TBD
|
||||
**Depends on:** Phase 11.2
|
||||
**Repos:** `sm-newsletter-plugin` (new, under `git.golem15.com/golem15/`, Go package `newsletter`), plus changes to the Phase 11.2 repos (`vue-summercms-app` for the widget and Polish locale, `sm-summercms-app` to wire the plugin). `summercms.go` changes only if a framework feature is missing.
|
||||
**Port source:** Golem15.Newsletter, `github.com/golem15com/wn-newsletter-plugin`, checked out at `/media/nvme/dev/golem15/horoskopia.eu/plugins/golem15/newsletter`. The PHP plugin is work in progress. Its audience comes from registered users (it requires `Golem15.User`), and its only public routes are unsubscribe. It has no public subscriber model or signup widget, so this phase adds those in Go. The PHP original is not changed.
|
||||
**Success Criteria** (what must be TRUE):
|
||||
|
||||
1. The newsletter plugin repo exists and ships an initial stub: a public signup endpoint (validated, honeypot and rate-limited, with required consent), double opt-in confirmation mail with a tokenized confirm link, a welcome mail, unsubscribe, and subscriber add, edit and delete in the admin SPA. Composing and sending newsletters is out of scope.
|
||||
2. The landing page has a signup widget that calls the plugin's API on the same origin and covers the pending, confirmed and error states, with localized result pages.
|
||||
3. The site is prerendered in English and Polish, and the confirmation and welcome mails follow the subscriber's locale.
|
||||
4. The new code has unit tests, delivered in the phase's last plan.
|
||||
|
||||
**Context:** decisions D-13 to D-22 in `.planning/phases/11.2-ready-to-share-summercms-io-website-and-newsletter-plugin/11.2-CONTEXT.md` (carried over from the original 11.2 discussion).
|
||||
|
||||
**Plans:** 0 plans
|
||||
|
||||
Plans:
|
||||
- [ ] TBD (run /gsd-plan-phase 11.3 to break down)
|
||||
|
||||
### Phase 12: Płytarium API — Collections and Albums
|
||||
|
||||
**Goal**: Collections and Albums endpoints are ported with byte-compatible request/response shapes, including active-context switching, editor invitations, ratings, reservations, cover handling and search.
|
||||
@@ -678,7 +700,8 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
|
||||
| 10. Admin Vue SPA | 5/5 | Complete | 2026-09-27 |
|
||||
| 11. Jobs, realtime and search infrastructure | 8/8 | In Progress| |
|
||||
| 11.1. SummerCMS documentation for humans and AI agents | 7/7 | In Progress| |
|
||||
| 11.2. Ready to share: summercms.io website and newsletter plugin | 0/TBD | Not started | - |
|
||||
| 11.2. summercms.io Alpha 0.1 landing page on SummerCMS | 0/TBD | Not started | - |
|
||||
| 11.3. Newsletter plugin and signup on summercms.io | 0/TBD | Not started | - |
|
||||
| 12. Płytarium API — Collections and Albums | 0/TBD | Not started | - |
|
||||
| 13. Płytarium API — wishlist, notifications, CSV, credentials, public routes | 0/TBD | Not started | - |
|
||||
| 14. Domain jobs and external integrations | 0/TBD | Not started | - |
|
||||
|
||||
@@ -5,12 +5,12 @@ current_phase: "11.1"
|
||||
current_phase_name: SummerCMS documentation for humans and AI agents (INSERTED)
|
||||
status: verifying
|
||||
stopped_at: Completed 11.1-07-PLAN.md
|
||||
last_updated: "2026-10-01T06:58:29.387Z"
|
||||
last_updated: "2026-10-01T11:49:35.390Z"
|
||||
last_activity: 2026-10-01
|
||||
last_activity_desc: Phase 11.1 execution started
|
||||
state_head: ce5dcec7e4e0733b07676b36abb26188d7150501
|
||||
state_head: 79116a2e036d36614819ed60276886f62556235b
|
||||
progress:
|
||||
total_phases: 19
|
||||
total_phases: 20
|
||||
completed_phases: 9
|
||||
total_plans: 93
|
||||
completed_plans: 93
|
||||
@@ -158,6 +158,8 @@ Progress: [██████░░░░] 60%
|
||||
- Phase 10.2 inserted after Phase 10: Nest framework packages under modules and write run docs (URGENT)
|
||||
- Phase 11.1 inserted after Phase 11: SummerCMS documentation for humans and AI agents, modelled on wintercms.com/docs; after core framework, before Płytarium API port
|
||||
- Phase 11.2 inserted after Phase 11.1: Ready to share: summercms.io website (sm-summercms-app + vue-summercms-app), sm-newsletter-plugin stub with double opt-in, 11.1 docs at /docs
|
||||
- Phase 11.2 edited: edited fields: title, goal, repos, design source, success_criteria — reshaped into the Alpha 0.1 landing page (Nuxt 4 on SummerCMS, nginx + supervisor deploy); newsletter moved to 11.3
|
||||
- Phase 11.3 inserted after Phase 11.2: Newsletter plugin and signup on summercms.io (split out of the original 11.2)
|
||||
|
||||
### Decisions
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
# Handoff: SummerCMS Alpha 0.1 Landing Page
|
||||
|
||||
## Overview
|
||||
A single-page marketing landing for **summercms.io**, launching with Alpha 0.1. It has a sticky header with section anchors and a link to `/docs`, a hero, four content sections (Why, Features, From WinterCMS, Get started) and a footer. It replaces the current "Under construction" page and keeps its navy, yellow and sun identity.
|
||||
|
||||
## About the Design Files
|
||||
`SummerCMS Landing.dc.html` is a **design reference built in HTML**. It shows the intended look and behavior and is not production code. Recreate it in the target site's stack. If the site has no stack yet, a static-site setup (Astro, Hugo, or a plain HTML/CSS page) is enough: the page is static apart from two small scripts (scroll-spy and copy-to-clipboard). The file loads a design-runtime script (`support.js`) for previewing; ignore it.
|
||||
|
||||
## Fidelity
|
||||
**High-fidelity.** Colors, type, spacing and copy are final. Match them exactly.
|
||||
|
||||
## Global
|
||||
- Page background `#233148`. Text `#e9edf3`.
|
||||
- Fonts: **Roboto** (300/400/500/700) and **Roboto Mono** (400/500), from Google Fonts.
|
||||
- `html { scroll-behavior: smooth; scroll-padding-top: 72px }` so anchor jumps clear the sticky header.
|
||||
- Content container: `max-width: 1120px; margin: 0 auto; padding: 0 24px`.
|
||||
- Section vertical padding: `96px` top and bottom.
|
||||
- Default link color `#f5c55a`; hover `#fbe3a6`. Selection: background `#f5c55a`, text `#1d2940`.
|
||||
|
||||
## Sections
|
||||
|
||||
### 1. Header (sticky)
|
||||
- `position: sticky; top: 0; z-index: 10`. Height 64px. Background `rgba(29,41,64,0.82)` with `backdrop-filter: blur(12px)`. Bottom border `1px solid rgba(255,255,255,0.07)`.
|
||||
- Row is flex, `align-items: center`, `gap: 16px`. Logo, the "ALPHA 0.1" pill and the Docs button all have `flex-shrink: 0` and `white-space: nowrap`.
|
||||
- **Logo** (links to `#top`): a 30px sun icon (masked to a circle, scaled 1.35) next to the wordmark "Summer" + "CMS". Roboto 700, 18px, letter-spacing -0.01em. "Summer" `#fff`, "CMS" `#fbd77e`.
|
||||
- **Pill** "ALPHA 0.1": 11px/500, letter-spacing 0.12em, color `#f5c55a`, border `1px solid rgba(245,197,90,0.35)`, radius 999px, padding 3px 9px.
|
||||
- **Section links**: Why `#why` · Features `#features` · From WinterCMS `#winter` · Get started `#start`.
|
||||
- Right-aligned in a `flex: 1; min-width: 0; overflow-x: auto` wrapper; the inner row has `margin-left: auto`.
|
||||
- Each link: 14px/500, padding 8px 12px, radius 999px, color `#c5ccd6`.
|
||||
- Active link: color `#f5c55a`, background `rgba(245,197,90,0.1)`.
|
||||
- **Hidden at viewport ≤ 720px.** Below that width the header shows only logo, pill and Docs.
|
||||
- **Docs button** → `/docs`: label "Docs →". Background `#f5c55a`, text `#1d2940`, 14px/500, padding 9px 16px, radius 999px. Hover background `#fbd77e`.
|
||||
|
||||
### 2. Hero (`#top`)
|
||||
- Padding 120px 24px 128px. Centered column, `text-align: center`, `overflow: hidden`.
|
||||
- **Rays** (behind everything, can be turned off): an absolutely positioned layer at `inset: -40% -20%`.
|
||||
- `background: repeating-conic-gradient(from 0deg at 50% 50%, rgba(255,255,255,0.035) 0deg 7deg, transparent 7deg 15deg)`
|
||||
- `mask: radial-gradient(circle, #000 10%, transparent 62%)`
|
||||
- **Glow**: a 520px circle centered 210px from the top, `radial-gradient(circle, rgba(245,197,90,0.16), transparent 60%)`.
|
||||
- **Sun badge**: 180px circle with border `1px solid rgba(255,255,255,0.12)` and background `#29344a`, containing the sun image.
|
||||
- **H1** "Summer" + "CMS": `clamp(44px, 7vw, 76px)`, weight 700, line-height 1, letter-spacing -0.02em, margin-top 28px.
|
||||
- "Summer" is `#fff`.
|
||||
- "CMS" uses a gradient text fill: `linear-gradient(180deg, #fde9b4, #f5c55a)`.
|
||||
- **Tagline** "A new dawn in content management": `clamp(18px, 2.2vw, 22px)`, weight 300, color `#c5ccd6`, margin-top 16px.
|
||||
- **Description**: max-width 600px, 17px, line-height 1.6, color `#a3adbd`, margin-top 24px. Copy: "A content management framework for Go, inspired by WinterCMS. Plugins, the admin SPA and console commands compile into a single binary."
|
||||
- **CTAs**: margin-top 40px, flex row, gap 12px, wraps on narrow screens.
|
||||
- Primary "Read the docs" → `/docs`: background `#f5c55a`, text `#1d2940`, 15px/500, padding 14px 26px, pill shape. Hover background `#fbd77e`.
|
||||
- Secondary "Alpha 0.1 is out" → `#start`: 8px `#f5c55a` dot before the label. Background `rgba(255,255,255,0.06)`, border `1px solid rgba(255,255,255,0.14)`, padding 13px 24px. Hover background `rgba(255,255,255,0.1)`.
|
||||
|
||||
### Section heading pattern (used in every content section)
|
||||
- Eyebrow: 12px/500, letter-spacing 0.16em, uppercase, `#f5c55a`.
|
||||
- H2: `clamp(30px, 4vw, 42px)`, weight 700, line-height 1.15, letter-spacing -0.015em, `#fff`, margin-top 12px.
|
||||
|
||||
### 3. Why (`#why`)
|
||||
- Eyebrow "WHY SUMMER". H2 "What you tested is exactly what you deploy." (max-width 720px).
|
||||
- Card grid: `repeat(auto-fit, minmax(260px, 1fr))`, gap 20px, margin-top 48px.
|
||||
- Cards: background `#29344a`, border `1px solid rgba(255,255,255,0.08)`, radius 16px, padding 28px.
|
||||
- Number: Roboto Mono 13px, `#f5c55a`.
|
||||
- Title: 20px/500, `#fff`, margin 16px 0 8px.
|
||||
- Body: 15px, line-height 1.6, `#a3adbd`.
|
||||
- Card copy:
|
||||
1. **One binary**: "Plugins are Go packages compiled in at build time. Nothing is scanned, loaded or installed at runtime."
|
||||
2. **YAML-driven admin**: "Describe lists and forms in `fields.yaml` and `columns.yaml`. An embedded SPA renders them." The file names use inline code: Roboto Mono 13px, `#e9edf3`.
|
||||
3. **Headless by design**: "A JSON API declared route by route, plus realtime channels. Build the public site in whatever frontend you like."
|
||||
|
||||
### 4. Features (`#features`)
|
||||
- Full-bleed band: background `#1f2b42`, top and bottom borders `1px solid rgba(255,255,255,0.07)`.
|
||||
- Eyebrow "WHAT'S IN THE BOX". H2 "The services a content app needs."
|
||||
- Grid: `repeat(auto-fill, minmax(240px, 1fr))`. The 1px dividers come from `gap: 1px` over a `rgba(255,255,255,0.08)` grid background. Outer border is the same color, radius 16px, `overflow: hidden`.
|
||||
- Each tile is a link: background `#1f2b42`, padding 24px, flex column, gap 6px. Hover background `#253350`.
|
||||
- Title: 16px/500, `#e9edf3`.
|
||||
- Body: 14px, line-height 1.5, `#a3adbd`.
|
||||
|
||||
| Title | Body | Link |
|
||||
|---|---|---|
|
||||
| Admin SPA | Embedded in the binary, driven by each plugin's YAML. | /docs/backend/admin-spa |
|
||||
| Models & migrations | GORM structs with fill, validation and pagination helpers. | /docs/database/models |
|
||||
| Routing & auth | Route groups, named middleware, tokens and OAuth. | /docs/services/routing |
|
||||
| Queued jobs | Dispatched inside the caller's transaction. | /docs/services/jobs |
|
||||
| Realtime | Broadcast model changes to subscribed clients. | /docs/services/realtime |
|
||||
| Search | Searchable models, synced after commit. | /docs/services/search |
|
||||
| Mail & push | Plugin mail templates and push notifications. | /docs/services/mail |
|
||||
| Console | Scaffolding, scheduler, workers and your own commands. | /docs/console/introduction |
|
||||
|
||||
*Doc URLs were derived from the docs folder structure. Confirm them against the built docs site.*
|
||||
|
||||
### 5. From WinterCMS (`#winter`)
|
||||
- Two columns: `repeat(auto-fit, minmax(300px, 1fr))`, gap 48px, `align-items: start`.
|
||||
- **Left column**
|
||||
- Eyebrow "COMING FROM WINTERCMS". H2 "Same shape. Compiled and typed."
|
||||
- Paragraph (16px, line-height 1.65, `#a3adbd`, margin-top 20px): "Plugins still register and boot, require each other, ship migrations and admin YAML. A plugin ports file by file."
|
||||
- Link "See the full concept map →" (15px/500) → `/docs/setup/coming-from-wintercms`.
|
||||
- **Right column: concept table**
|
||||
- Container: background `#29344a`, border `rgba(255,255,255,0.08)`, radius 16px.
|
||||
- Header row "WINTERCMS | SUMMERCMS": 12px/500, letter-spacing 0.12em, `#8a94a3`.
|
||||
- Rows: grid `1fr 1.3fr`, padding 14px 20px, Roboto Mono 13px, divider `rgba(255,255,255,0.06)`. Left cell `#a3adbd`, right cell `#fbe3a6`.
|
||||
- Row content:
|
||||
|
||||
| WinterCMS | SummerCMS |
|
||||
|---|---|
|
||||
| Plugin.php | party.Plugin |
|
||||
| version.yaml + updates/ | pact.HasMigrations |
|
||||
| Eloquent models | GORM + lagoon |
|
||||
| fields.yaml / columns.yaml | Same YAML, compiled at boot |
|
||||
| routes.php | pact.HasRoutes |
|
||||
| Event::listen / fire | festival.Bus |
|
||||
| Artisan commands | bonfire.Command |
|
||||
|
||||
### 6. Get started (`#start`)
|
||||
- Full-bleed band: background `#1f2b42`, top border `rgba(255,255,255,0.07)`.
|
||||
- Two columns, same grid as the WinterCMS section, `align-items: center`.
|
||||
- **Left column**
|
||||
- Eyebrow "GET STARTED". H2 "Build your first app."
|
||||
- Requirement chips "Go 1.27" and "PostgreSQL 16": 13px, `#c5ccd6`, background `rgba(255,255,255,0.06)`, border `rgba(255,255,255,0.1)`, pill shape, padding 6px 12px.
|
||||
- Note: "Alpha 0.1 is for early adopters. APIs may change before 1.0."
|
||||
- Buttons:
|
||||
- "Installation guide" (primary style) → `/docs/setup/installation`.
|
||||
- "Source" (outline style) → `https://git.golem15.com/golem15/summercms`.
|
||||
- **Right column: terminal card**
|
||||
- Background `#18223a`, border `rgba(255,255,255,0.08)`, radius 16px.
|
||||
- Title bar: label "terminal" (Roboto Mono 12px, `#8a94a3`) and a **Copy** button (12px/500, `#c5ccd6`, background `rgba(255,255,255,0.06)`, border `rgba(255,255,255,0.1)`, radius 6px, padding 5px 10px).
|
||||
- Body: padding 22px 20px, Roboto Mono 14px, line-height 1.9.
|
||||
- **Each line is its own block element.** Comments are `#8a94a3`. The `$ ` prompt is `#f5c55a`. A 16px gap separates the two groups.
|
||||
```
|
||||
# install the summer CLI
|
||||
$ go install ./cmd/summer
|
||||
|
||||
# build and run the example app
|
||||
$ cd examples/hello
|
||||
$ summer build
|
||||
$ ./bin/hello greeter:hello
|
||||
```
|
||||
|
||||
### 7. Footer
|
||||
- Top border `rgba(255,255,255,0.07)`. Padding 32px 24px. 13px, `#8a94a3`.
|
||||
- Left: "© 2026 SummerCMS. Something bright is here."
|
||||
- Right links (`#a3adbd`, hover `#f5c55a`, gap 20px):
|
||||
- Docs → `/docs`
|
||||
- Source → `https://git.golem15.com/golem15/summercms`
|
||||
- Back to top ↑ → `#top`
|
||||
|
||||
## Interactions & Behavior
|
||||
- **Scroll-spy**: on window scroll, the active section is the last of `why`, `features`, `winter`, `start` whose top is less than 140px from the viewport top. That link gets the active style. Above the first section, no link is active.
|
||||
- **Copy button**: writes the four commands (without `$` or comments) to the clipboard. The label changes to "Copied" for 1.5s, then reverts.
|
||||
- **Responsive**: every grid uses auto-fit/auto-fill and collapses to one column on its own. Section links hide at ≤ 720px. Hero type scales with `clamp()`.
|
||||
- **Transitions**: none are specified. Hover changes are instant; a 150ms ease on background and color is fine.
|
||||
|
||||
## State
|
||||
- `activeSection: string`
|
||||
- `copied: boolean`
|
||||
- `isWide: boolean` (matchMedia `min-width: 721px`)
|
||||
|
||||
The prototype also has two config flags: `showRays` (default true) and `scrollSpy` (default true).
|
||||
|
||||
## Design Tokens
|
||||
| Token | Hex | Used for |
|
||||
|---|---|---|
|
||||
| navy-900 | `#18223a` | terminal background |
|
||||
| navy-850 | `#1d2940` | header base, text on yellow |
|
||||
| navy-800 | `#1f2b42` | alternate bands |
|
||||
| navy-700 | `#233148` | page background |
|
||||
| navy-650 | `#253350` | feature tile hover |
|
||||
| navy-600 | `#29344a` | cards |
|
||||
| yellow-500 | `#f5c55a` | accent |
|
||||
| yellow-400 | `#fbd77e` | accent hover, "CMS" in logo |
|
||||
| yellow-200 | `#fbe3a6` | link hover, code values |
|
||||
| yellow-100 | `#fde9b4` | top of the "CMS" gradient |
|
||||
| text | `#e9edf3` | body text |
|
||||
| text-2 | `#c5ccd6` | tagline, nav links |
|
||||
| text-3 | `#a3adbd` | body copy |
|
||||
| text-4 | `#8a94a3` | captions, comments |
|
||||
|
||||
- Borders: white at 6, 7, 8, 10, 12 and 14% alpha.
|
||||
- Radius: 6px (small button), 16px (cards), 999px (pills).
|
||||
- Spacing in use: 4, 6, 8, 12, 16, 20, 24, 28, 32, 40, 48, 96 and 120px.
|
||||
|
||||
## Assets
|
||||
- `assets/sun-crop.png` (180×180): **a placeholder cropped from a screenshot** of the current under-construction page. Replace it with the original sun artwork from the existing summercms.io site. A transparent PNG or SVG is best; the hero badge then provides the circle and border.
|
||||
|
||||
## Files
|
||||
- `SummerCMS Landing.dc.html`: the full design reference.
|
||||
- `assets/sun-crop.png`: the placeholder sun icon.
|
||||
@@ -0,0 +1,223 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&family=Roboto+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
html{scroll-behavior:smooth;scroll-padding-top:72px}
|
||||
body{margin:0;background:#233148;color:#e9edf3;font-family:Roboto,system-ui,sans-serif;-webkit-font-smoothing:antialiased}
|
||||
a{color:#f5c55a;text-decoration:none}
|
||||
a:hover{color:#fbe3a6}
|
||||
::selection{background:#f5c55a;color:#1d2940}
|
||||
</style>
|
||||
</helmet>
|
||||
|
||||
<div style="min-height:100vh;background:#233148;overflow-x:hidden">
|
||||
|
||||
<header style="position:sticky;top:0;z-index:10;background:rgba(29,41,64,0.82);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-bottom:1px solid rgba(255,255,255,0.07)">
|
||||
<nav style="max-width:1120px;margin:0 auto;padding:0 24px;height:64px;display:flex;align-items:center;gap:16px">
|
||||
<a href="#top" style="flex-shrink:0;white-space:nowrap;display:flex;align-items:center;gap:10px;color:#fff;font-weight:700;font-size:18px;letter-spacing:-0.01em">
|
||||
<img src="assets/sun-crop.png" alt="" style="width:30px;height:30px;-webkit-mask-image:radial-gradient(circle,#000 52%,transparent 70%);mask-image:radial-gradient(circle,#000 52%,transparent 70%);transform:scale(1.35)">
|
||||
<span>Summer<span style="color:#fbd77e">CMS</span></span>
|
||||
</a>
|
||||
<span style="flex-shrink:0;white-space:nowrap;font-size:11px;font-weight:500;letter-spacing:0.12em;color:#f5c55a;border:1px solid rgba(245,197,90,0.35);border-radius:999px;padding:3px 9px">ALPHA 0.1</span>
|
||||
<div style="flex:1;display:flex;min-width:0;overflow-x:auto;scrollbar-width:none">
|
||||
<sc-if value="{{ wide }}" hint-placeholder-val="{{ true }}">
|
||||
<div style="display:flex;gap:4px;flex-wrap:nowrap;margin-left:auto">
|
||||
<sc-for list="{{ navItems }}" as="n" hint-placeholder-count="4">
|
||||
<a href="{{ n.href }}" style="{{ n.style }}">{{ n.label }}</a>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
<a href="/docs" style="flex-shrink:0;white-space:nowrap;display:flex;align-items:center;gap:8px;background:#f5c55a;color:#1d2940;font-weight:500;font-size:14px;padding:9px 16px;border-radius:999px" style-hover="background:#fbd77e;color:#1d2940">Docs <span>→</span></a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section id="top" data-screen-label="Hero" style="position:relative;padding:120px 24px 128px;display:flex;flex-direction:column;align-items:center;text-align:center;overflow:hidden">
|
||||
<sc-if value="{{ showRays }}" hint-placeholder-val="{{ true }}">
|
||||
<div style="position:absolute;inset:-40% -20%;background:repeating-conic-gradient(from 0deg at 50% 50%,rgba(255,255,255,0.035) 0deg 7deg,rgba(255,255,255,0) 7deg 15deg);-webkit-mask-image:radial-gradient(circle at 50% 50%,#000 10%,transparent 62%);mask-image:radial-gradient(circle at 50% 50%,#000 10%,transparent 62%);pointer-events:none"></div>
|
||||
</sc-if>
|
||||
<div style="position:absolute;left:50%;top:210px;width:520px;height:520px;transform:translate(-50%,-50%);background:radial-gradient(circle,rgba(245,197,90,0.16),transparent 60%);pointer-events:none"></div>
|
||||
<div style="position:relative;width:180px;height:180px;border-radius:50%;border:1px solid rgba(255,255,255,0.12);display:flex;align-items:center;justify-content:center;background:#29344a">
|
||||
<img src="assets/sun-crop.png" alt="SummerCMS sun" style="width:180px;height:180px;border-radius:50%">
|
||||
</div>
|
||||
<h1 style="position:relative;margin:28px 0 0;font-size:clamp(44px,7vw,76px);line-height:1;font-weight:700;letter-spacing:-0.02em;color:#fff">Summer<span style="background:linear-gradient(180deg,#fde9b4,#f5c55a);-webkit-background-clip:text;background-clip:text;color:transparent">CMS</span></h1>
|
||||
<p style="position:relative;margin:16px 0 0;font-size:clamp(18px,2.2vw,22px);font-weight:300;letter-spacing:0.01em;color:#c5ccd6">A new dawn in content management</p>
|
||||
<p style="position:relative;margin:24px 0 0;max-width:600px;font-size:17px;line-height:1.6;color:#a3adbd;text-wrap:pretty">A content management framework for Go, inspired by WinterCMS. Plugins, the admin SPA and console commands compile into a single binary.</p>
|
||||
<div style="position:relative;margin-top:40px;display:flex;gap:12px;flex-wrap:wrap;justify-content:center">
|
||||
<a href="/docs" style="background:#f5c55a;color:#1d2940;font-weight:500;font-size:15px;padding:14px 26px;border-radius:999px" style-hover="background:#fbd77e;color:#1d2940">Read the docs</a>
|
||||
<a href="#start" style="display:flex;align-items:center;gap:10px;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.14);color:#e9edf3;font-weight:500;font-size:15px;padding:13px 24px;border-radius:999px" style-hover="background:rgba(255,255,255,0.1);color:#fff"><span style="width:8px;height:8px;border-radius:50%;background:#f5c55a"></span>Alpha 0.1 is out</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="why" data-screen-label="Why" style="max-width:1120px;margin:0 auto;padding:96px 24px">
|
||||
<div style="font-size:12px;font-weight:500;letter-spacing:0.16em;color:#f5c55a">WHY SUMMER</div>
|
||||
<h2 style="margin:12px 0 0;max-width:720px;font-size:clamp(30px,4vw,42px);line-height:1.15;font-weight:700;letter-spacing:-0.015em;color:#fff;text-wrap:pretty">What you tested is exactly what you deploy.</h2>
|
||||
<div style="margin-top:48px;display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:20px">
|
||||
<div style="background:#29344a;border:1px solid rgba(255,255,255,0.08);border-radius:16px;padding:28px">
|
||||
<div style="font-family:'Roboto Mono',monospace;font-size:13px;color:#f5c55a">01</div>
|
||||
<h3 style="margin:16px 0 8px;font-size:20px;font-weight:500;color:#fff">One binary</h3>
|
||||
<p style="margin:0;font-size:15px;line-height:1.6;color:#a3adbd;text-wrap:pretty">Plugins are Go packages compiled in at build time. Nothing is scanned, loaded or installed at runtime.</p>
|
||||
</div>
|
||||
<div style="background:#29344a;border:1px solid rgba(255,255,255,0.08);border-radius:16px;padding:28px">
|
||||
<div style="font-family:'Roboto Mono',monospace;font-size:13px;color:#f5c55a">02</div>
|
||||
<h3 style="margin:16px 0 8px;font-size:20px;font-weight:500;color:#fff">YAML-driven admin</h3>
|
||||
<p style="margin:0;font-size:15px;line-height:1.6;color:#a3adbd;text-wrap:pretty">Describe lists and forms in <code style="font-family:'Roboto Mono',monospace;font-size:13px;color:#e9edf3">fields.yaml</code> and <code style="font-family:'Roboto Mono',monospace;font-size:13px;color:#e9edf3">columns.yaml</code>. An embedded SPA renders them.</p>
|
||||
</div>
|
||||
<div style="background:#29344a;border:1px solid rgba(255,255,255,0.08);border-radius:16px;padding:28px">
|
||||
<div style="font-family:'Roboto Mono',monospace;font-size:13px;color:#f5c55a">03</div>
|
||||
<h3 style="margin:16px 0 8px;font-size:20px;font-weight:500;color:#fff">Headless by design</h3>
|
||||
<p style="margin:0;font-size:15px;line-height:1.6;color:#a3adbd;text-wrap:pretty">A JSON API declared route by route, plus realtime channels. Build the public site in whatever frontend you like.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="features" data-screen-label="Features" style="border-top:1px solid rgba(255,255,255,0.07);border-bottom:1px solid rgba(255,255,255,0.07);background:#1f2b42">
|
||||
<div style="max-width:1120px;margin:0 auto;padding:96px 24px">
|
||||
<div style="font-size:12px;font-weight:500;letter-spacing:0.16em;color:#f5c55a">WHAT'S IN THE BOX</div>
|
||||
<h2 style="margin:12px 0 0;max-width:720px;font-size:clamp(30px,4vw,42px);line-height:1.15;font-weight:700;letter-spacing:-0.015em;color:#fff">The services a content app needs.</h2>
|
||||
<div style="margin-top:48px;display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:1px;background:rgba(255,255,255,0.08);border:1px solid rgba(255,255,255,0.08);border-radius:16px;overflow:hidden">
|
||||
<sc-for list="{{ features }}" as="f" hint-placeholder-count="8">
|
||||
<a href="{{ f.href }}" style="display:flex;flex-direction:column;gap:6px;background:#1f2b42;padding:24px;color:#e9edf3" style-hover="background:#253350;color:#fff">
|
||||
<span style="font-size:16px;font-weight:500">{{ f.title }}</span>
|
||||
<span style="font-size:14px;line-height:1.5;color:#a3adbd">{{ f.body }}</span>
|
||||
</a>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="winter" data-screen-label="From WinterCMS" style="max-width:1120px;margin:0 auto;padding:96px 24px;display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:48px;align-items:start">
|
||||
<div>
|
||||
<div style="font-size:12px;font-weight:500;letter-spacing:0.16em;color:#f5c55a">COMING FROM WINTERCMS</div>
|
||||
<h2 style="margin:12px 0 0;font-size:clamp(30px,4vw,42px);line-height:1.15;font-weight:700;letter-spacing:-0.015em;color:#fff;text-wrap:pretty">Same shape. Compiled and typed.</h2>
|
||||
<p style="margin:20px 0 0;font-size:16px;line-height:1.65;color:#a3adbd;text-wrap:pretty">Plugins still register and boot, require each other, ship migrations and admin YAML. A plugin ports file by file.</p>
|
||||
<a href="/docs/setup/coming-from-wintercms" style="display:inline-flex;margin-top:24px;font-weight:500;font-size:15px">See the full concept map →</a>
|
||||
</div>
|
||||
<div style="border:1px solid rgba(255,255,255,0.08);border-radius:16px;overflow:hidden;background:#29344a">
|
||||
<div style="display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.3fr);padding:14px 20px;font-size:12px;font-weight:500;letter-spacing:0.12em;color:#8a94a3;border-bottom:1px solid rgba(255,255,255,0.08)">
|
||||
<span>WINTERCMS</span><span>SUMMERCMS</span>
|
||||
</div>
|
||||
<sc-for list="{{ concepts }}" as="c" hint-placeholder-count="6">
|
||||
<div style="display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.3fr);gap:12px;padding:14px 20px;border-bottom:1px solid rgba(255,255,255,0.06);font-family:'Roboto Mono',monospace;font-size:13px;line-height:1.5">
|
||||
<span style="color:#a3adbd">{{ c.w }}</span>
|
||||
<span style="color:#fbe3a6">{{ c.s }}</span>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="start" data-screen-label="Get started" style="border-top:1px solid rgba(255,255,255,0.07);background:#1f2b42">
|
||||
<div style="max-width:1120px;margin:0 auto;padding:96px 24px;display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:48px;align-items:center">
|
||||
<div>
|
||||
<div style="font-size:12px;font-weight:500;letter-spacing:0.16em;color:#f5c55a">GET STARTED</div>
|
||||
<h2 style="margin:12px 0 0;font-size:clamp(30px,4vw,42px);line-height:1.15;font-weight:700;letter-spacing:-0.015em;color:#fff">Build your first app.</h2>
|
||||
<div style="margin-top:24px;display:flex;gap:8px;flex-wrap:wrap">
|
||||
<span style="font-size:13px;color:#c5ccd6;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);border-radius:999px;padding:6px 12px">Go 1.27</span>
|
||||
<span style="font-size:13px;color:#c5ccd6;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);border-radius:999px;padding:6px 12px">PostgreSQL 16</span>
|
||||
</div>
|
||||
<p style="margin:20px 0 0;font-size:16px;line-height:1.65;color:#a3adbd;text-wrap:pretty">Alpha 0.1 is for early adopters. APIs may change before 1.0.</p>
|
||||
<div style="margin-top:28px;display:flex;gap:12px;flex-wrap:wrap">
|
||||
<a href="/docs/setup/installation" style="background:#f5c55a;color:#1d2940;font-weight:500;font-size:15px;padding:13px 24px;border-radius:999px" style-hover="background:#fbd77e;color:#1d2940">Installation guide</a>
|
||||
<a href="https://git.golem15.com/golem15/summercms" style="border:1px solid rgba(255,255,255,0.14);color:#e9edf3;font-weight:500;font-size:15px;padding:12px 22px;border-radius:999px" style-hover="background:rgba(255,255,255,0.08);color:#fff">Source</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background:#18223a;border:1px solid rgba(255,255,255,0.08);border-radius:16px;overflow:hidden">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;padding:12px 18px;border-bottom:1px solid rgba(255,255,255,0.07)">
|
||||
<span style="font-family:'Roboto Mono',monospace;font-size:12px;color:#8a94a3">terminal</span>
|
||||
<button onClick="{{ copy }}" style="font:500 12px Roboto,sans-serif;color:#c5ccd6;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);border-radius:6px;padding:5px 10px;cursor:pointer">{{ copyLabel }}</button>
|
||||
</div>
|
||||
<div style="padding:22px 20px;font-family:'Roboto Mono',monospace;font-size:14px;line-height:1.9;color:#e9edf3;overflow-x:auto;display:flex;flex-direction:column">
|
||||
<span style="color:#8a94a3;white-space:pre"># install the summer CLI</span>
|
||||
<span style="white-space:pre"><span style="color:#f5c55a">$ </span>go install ./cmd/summer</span>
|
||||
<span style="color:#8a94a3;white-space:pre;margin-top:16px"># build and run the example app</span>
|
||||
<span style="white-space:pre"><span style="color:#f5c55a">$ </span>cd examples/hello</span>
|
||||
<span style="white-space:pre"><span style="color:#f5c55a">$ </span>summer build</span>
|
||||
<span style="white-space:pre"><span style="color:#f5c55a">$ </span>./bin/hello greeter:hello</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer style="border-top:1px solid rgba(255,255,255,0.07)">
|
||||
<div style="max-width:1120px;margin:0 auto;padding:32px 24px;display:flex;gap:24px;align-items:center;flex-wrap:wrap;font-size:13px;color:#8a94a3">
|
||||
<span>© 2026 SummerCMS. Something bright is here.</span>
|
||||
<div style="flex:1"></div>
|
||||
<div style="display:flex;gap:20px">
|
||||
<a href="/docs" style="color:#a3adbd" style-hover="color:#f5c55a">Docs</a>
|
||||
<a href="https://git.golem15.com/golem15/summercms" style="color:#a3adbd" style-hover="color:#f5c55a">Source</a>
|
||||
<a href="#top" style="color:#a3adbd" style-hover="color:#f5c55a">Back to top ↑</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props="{"showRays":{"editor":"boolean","default":true,"tsType":"boolean"},"scrollSpy":{"editor":"boolean","default":true,"tsType":"boolean"}}">
|
||||
class Component extends DCLogic {
|
||||
state = { active: '', copied: false, wide: window.innerWidth > 720 };
|
||||
sections = [['why','Why'],['features','Features'],['winter','From WinterCMS'],['start','Get started']];
|
||||
componentDidMount() {
|
||||
this.onScroll = () => {
|
||||
let a = '';
|
||||
for (const [id] of this.sections) {
|
||||
const el = document.getElementById(id);
|
||||
if (el && el.getBoundingClientRect().top < 140) a = id;
|
||||
}
|
||||
if (a !== this.state.active) this.setState({ active: a });
|
||||
};
|
||||
window.addEventListener('scroll', this.onScroll, { passive: true });
|
||||
this.mq = window.matchMedia('(min-width: 721px)');
|
||||
this.onMq = () => this.setState({ wide: this.mq.matches });
|
||||
this.mq.addEventListener('change', this.onMq);
|
||||
this.onScroll();
|
||||
}
|
||||
componentWillUnmount() { window.removeEventListener('scroll', this.onScroll); this.mq?.removeEventListener('change', this.onMq); }
|
||||
renderVals() {
|
||||
const spy = this.props.scrollSpy ?? true;
|
||||
return {
|
||||
showRays: this.props.showRays ?? true,
|
||||
wide: this.state.wide,
|
||||
navItems: this.sections.map(([id, label]) => {
|
||||
const on = spy && this.state.active === id;
|
||||
return { href: '#' + id, label, style: `white-space:nowrap;flex-shrink:0;font-size:14px;font-weight:500;padding:8px 12px;border-radius:999px;color:${on ? '#f5c55a' : '#c5ccd6'};background:${on ? 'rgba(245,197,90,0.1)' : 'transparent'}` };
|
||||
}),
|
||||
features: [
|
||||
{ title: 'Admin SPA', body: 'Embedded in the binary, driven by each plugin’s YAML.', href: '/docs/backend/admin-spa' },
|
||||
{ title: 'Models & migrations', body: 'GORM structs with fill, validation and pagination helpers.', href: '/docs/database/models' },
|
||||
{ title: 'Routing & auth', body: 'Route groups, named middleware, tokens and OAuth.', href: '/docs/services/routing' },
|
||||
{ title: 'Queued jobs', body: 'Dispatched inside the caller’s transaction.', href: '/docs/services/jobs' },
|
||||
{ title: 'Realtime', body: 'Broadcast model changes to subscribed clients.', href: '/docs/services/realtime' },
|
||||
{ title: 'Search', body: 'Searchable models, synced after commit.', href: '/docs/services/search' },
|
||||
{ title: 'Mail & push', body: 'Plugin mail templates and push notifications.', href: '/docs/services/mail' },
|
||||
{ title: 'Console', body: 'Scaffolding, scheduler, workers and your own commands.', href: '/docs/console/introduction' },
|
||||
],
|
||||
concepts: [
|
||||
{ w: 'Plugin.php', s: 'party.Plugin' },
|
||||
{ w: 'version.yaml + updates/', s: 'pact.HasMigrations' },
|
||||
{ w: 'Eloquent models', s: 'GORM + lagoon' },
|
||||
{ w: 'fields.yaml / columns.yaml', s: 'Same YAML, compiled at boot' },
|
||||
{ w: 'routes.php', s: 'pact.HasRoutes' },
|
||||
{ w: 'Event::listen / fire', s: 'festival.Bus' },
|
||||
{ w: 'Artisan commands', s: 'bonfire.Command' },
|
||||
],
|
||||
copyLabel: this.state.copied ? 'Copied' : 'Copy',
|
||||
copy: () => {
|
||||
navigator.clipboard?.writeText('go install ./cmd/summer\ncd examples/hello\nsummer build\n./bin/hello greeter:hello');
|
||||
this.setState({ copied: true });
|
||||
setTimeout(() => this.setState({ copied: false }), 1500);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1 @@
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
},
|
||||
{
|
||||
"number": "11.2",
|
||||
"name": "Ready to share: summercms.io website and newsletter plugin",
|
||||
"name": "summercms.io Alpha 0.1 landing page on SummerCMS",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
@@ -94,5 +94,5 @@
|
||||
"label": "Advance to the next step (verify)",
|
||||
"reason": "Phase 11.1 of 19 · ready to verify"
|
||||
},
|
||||
"updated_at": "2026-10-01T06:58:29.408Z"
|
||||
"updated_at": "2026-10-01T11:49:17.622Z"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user