genesis-stack 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,153 @@
1
+ # Stack piece: nextjs
2
+
3
+ ## Description
4
+
5
+ Next.js React application conventions: App Router or Pages Router, the
6
+ `next` CLI, Server Actions, middleware, environment variables, builds and
7
+ production serving. A Next.js application has `next` in `package.json`
8
+ dependencies and usually a `next.config.js`, `next.config.mjs` or
9
+ `next.config.ts` file and an `app/` or `pages/` directory. Authoritative
10
+ framework documentation: https://nextjs.org/docs
11
+
12
+ ## Requires
13
+
14
+ - `nodejs`
15
+
16
+ ## Conflicts
17
+
18
+ - `express`
19
+
20
+ ## Guidance
21
+
22
+ - Match the installed Next.js major version and the router the application
23
+ already uses (`app/` App Router or `pages/` Pages Router). Recent releases
24
+ ship version-matched documentation in `node_modules/next/dist/docs/`; read
25
+ the relevant guide there before relying on remembered APIs. `next dev` may
26
+ write a framework-owned agent-rules block into `AGENTS.md`; commit it rather
27
+ than repeatedly removing it.
28
+ - Bind the development server to the host and port it is given:
29
+ `next dev --hostname <host> --port <port>` (the proposed Run passes them
30
+ through `npm run dev --`). Without `--hostname`, `next dev` and `next start`
31
+ listen on every interface. Never hard-code a port in `package.json` scripts.
32
+ - Behind a development reverse proxy on loopback that rewrites `Host` and sends
33
+ `X-Forwarded-Host`, `X-Forwarded-Proto` and `X-Forwarded-Port`, Next.js
34
+ builds request URLs from the forwarded headers. The development server blocks
35
+ requests for its own development resources (the `/_next/hmr` WebSocket and
36
+ other `/_next/*` dev endpoints) whose `Origin` hostname is not `localhost`,
37
+ the hostname it was started with, or an `allowedDevOrigins` entry. A proxy
38
+ that rewrites the browser's `Origin` to the loopback address needs no entry;
39
+ otherwise add the browser-facing hostname pattern to `allowedDevOrigins`,
40
+ read from an environment variable rather than hard-coded. The HMR client
41
+ connects through the page's own origin; do not hard-code an asset prefix or
42
+ WebSocket host for the proxy.
43
+ - Server Actions reject a POST whose `Origin` host differs from
44
+ `X-Forwarded-Host` (or `Host` without it) with "Invalid Server Actions
45
+ request". When a development proxy rewrites `Origin` to the loopback address
46
+ while forwarding the browser host, admit exactly that loopback host in
47
+ `experimental.serverActions.allowedOrigins` in development only, for example
48
+ `` process.env.NODE_ENV === "development" && process.env.PORT ? [`127.0.0.1:${process.env.PORT}`] : [] ``
49
+ (ports cannot be wildcarded). The list also applies in production; never
50
+ admit arbitrary origins there.
51
+ - `NEXT_PUBLIC_*` variables are inlined into client bundles at build time:
52
+ never put secrets in them, and their production values must exist when
53
+ `next build` runs, not only at start. Server-only values are read from
54
+ `process.env` at request time. Next.js reads `.env*` files but the
55
+ environment wins; keep real values out of committed `.env*` files.
56
+ - With Auth.js (`next-auth` v5), supply `AUTH_SECRET` through the environment
57
+ (generate with `openssl rand -base64 33`; `npx auth secret` writes it into a
58
+ file instead) and set `AUTH_TRUST_HOST=true` when the app is served behind a
59
+ trusted reverse proxy, so callback and redirect URLs use the forwarded
60
+ origin. Other auth libraries need their equivalent trusted-host setting.
61
+ - Readiness and health probes must reach a public route: middleware (or
62
+ `proxy`) that redirects `/` to a login page makes a `GET /` probe fail.
63
+ Exclude the probe path from the auth matcher, or add a small public route
64
+ handler (for example `app/health/route.ts`) and point the Outputs and
65
+ Deployment readiness checks at it.
66
+ - Database access goes through the application's ORM (Prisma, Drizzle, Kysely
67
+ or another). Its schema migrations are application-owned: deployment runs the
68
+ non-interactive apply command (for example `prisma migrate deploy`), never
69
+ `prisma migrate dev` or `prisma db push` against supplied data. Seed scripts
70
+ must be idempotent. Tests use a disposable database supplied for them, never
71
+ the development or production database. Declare the database Resources in
72
+ the project Stack; this piece does not choose a database.
73
+ - Production: `next build` then `next start`. `next start` reads `PORT` but not
74
+ `HOST`; bind it explicitly (`next start --hostname <host>`), as the proposed
75
+ Serve does. Set `NODE_ENV=production` only through the production
76
+ environment, never as a project-wide default; `next build` and `next start`
77
+ set it themselves. `output: "standalone"` changes the start command to
78
+ `node .next/standalone/server.js` (which reads `HOSTNAME` and `PORT`) and
79
+ requires copying `public/` and `.next/static/`; update Deployment if the
80
+ application uses it. `output: "export"` produces static files with no server.
81
+ - Do not run `next build` into the same `.next` directory a running `next dev`
82
+ uses unless the installed major isolates development output (Next.js 16 and
83
+ later write development output to `.next/dev`); with older majors stop the
84
+ development server first or build into a separate `distDir`.
85
+ - When the application has login, seed one administrator and one ordinary user
86
+ for development through an idempotent seed script with credentials from the
87
+ environment, and keep role checks on the server (Server Components, route
88
+ handlers, Server Actions), not only in client components.
89
+
90
+ ## Adoption
91
+
92
+ - Inventory the real files before changing project contracts: the installed
93
+ `next` version in the lockfile, `app/` or `pages/`, `next.config.*` (`output`,
94
+ `basePath`, `distDir`, `experimental`), `middleware.*`/`proxy.*`, the auth
95
+ library and its environment names, the ORM and its migration commands, and
96
+ the real `dev`, `build`, `start`, `lint` and `test` scripts.
97
+ - Identify the package manager from the lockfile and replace every proposed
98
+ `npm` line when the project uses pnpm, Yarn or Bun. Next.js 16 removed
99
+ `next lint`; if the `lint` script is missing, remove that Verification line
100
+ instead of inventing one, and add the project's real test command when it
101
+ has one.
102
+ - Replace the readiness path when `/` is not publicly reachable, a `basePath`
103
+ is set, or a dedicated health route exists. Replace the Serve line for
104
+ `output: "standalone"`, a custom server, or `output: "export"`.
105
+ - A custom Next.js server built on Express is a project-owned decision: keep
106
+ this piece and describe that server's real commands in the project's own
107
+ sections.
108
+
109
+ ## Workspace setup
110
+
111
+ - Prepare `Install dependencies` with `nodejs` when `package.json` exists: `npm` `install`
112
+
113
+ ## Outputs
114
+
115
+ ### Target `app`: Run Next.js app
116
+
117
+ - Default.
118
+ - Mode: `interactive`
119
+ - Runtimes: `nodejs`
120
+ - Run `Develop`: `npm` `run` `dev` `--` `--hostname` `{host}` `--port` `{port}`
121
+
122
+ #### Presentation
123
+
124
+ - Kind: `web`
125
+ - Preferred port: `3000`
126
+ - URL path: `/`
127
+ - Ready when: `GET` `/` returns `200`
128
+
129
+ ## Verification
130
+
131
+ - Verify `lint`: `npm` `run` `lint`
132
+ - Verify `build`: `npm` `run` `build`
133
+
134
+ ## Deployment
135
+
136
+ - Runtimes: `nodejs`
137
+ - Recreate on restore: `node_modules` `.next/cache`
138
+ - Ready when: `GET` `/` returns `200`
139
+ - Prepare `Install dependencies`: `npm` `ci`
140
+ - Build `Build`: `npm` `run` `build`
141
+ - Serve `Start`: `npm` `start` `--` `--hostname` `127.0.0.1`
142
+
143
+ ## Deslop
144
+
145
+ - Keep data fetching in Server Components, route handlers and Server Actions
146
+ where the router supports it; remove client-side fetch wrappers that only
147
+ duplicate a server read.
148
+ - Keep `"use client"` boundaries as low in the tree as possible and do not mark
149
+ whole layouts as client components to reach one interactive widget.
150
+ - Use the framework's `Link`, `Image`, `Script`, metadata and font facilities
151
+ instead of hand-written equivalents.
152
+ - Remove abandoned starter content, unused route segments and duplicate
153
+ environment readers only when routes, redirects and tests stay unchanged.
@@ -43,7 +43,8 @@ Node.js package, command, module, dependency, and test conventions.
43
43
  connected source root. An ordinary `npm ci` restores the published packages.
44
44
  - Long-running web processes accept their listen host and port from arguments
45
45
  or the environment rather than hard-coding them, and fail if the port is
46
- taken instead of silently choosing another.
46
+ taken instead of silently choosing another. For Express or Next.js select
47
+ `express` or `nextjs`; that piece owns the framework traps.
47
48
 
48
49
  ## Adoption
49
50
 
@@ -44,11 +44,9 @@ Python package, module, callable, dependency, and test conventions.
44
44
  `[tool.uv.sources]` and lockfile changes.
45
45
  - Running a web process: bind the supplied listen host and port, trust forwarded
46
46
  headers only from a loopback proxy, and read secrets from the environment.
47
- Django: set `ALLOWED_HOSTS` and `CSRF_TRUSTED_ORIGINS` for the served origin
48
- (`ALLOWED_HOSTS` also lists the loopback host the proxy connects to),
49
- `SECURE_PROXY_SSL_HEADER` and `USE_X_FORWARDED_HOST` only behind that trusted
50
- proxy, and read `SECRET_KEY` from the environment. Flask uses Werkzeug's
51
- `ProxyFix`; Uvicorn uses `--proxy-headers --forwarded-allow-ips 127.0.0.1`.
47
+ For Django select `django`; its piece owns the framework traps. Flask uses
48
+ Werkzeug's `ProxyFix`; Uvicorn uses `--proxy-headers --forwarded-allow-ips
49
+ 127.0.0.1`.
52
50
 
53
51
  ## Connected development
54
52
 
@@ -0,0 +1,76 @@
1
+ # Stack piece: rails-mysql
2
+
3
+ ## Description
4
+
5
+ Rails MySQL connection, Active Record migration, and database environment conventions.
6
+
7
+ ## Requires
8
+
9
+ - `rails`
10
+ - `mysql`
11
+
12
+ ## Conflicts
13
+
14
+ - `rails-postgresql`
15
+ - `rails-sqlite`
16
+
17
+ ## Environment defaults
18
+
19
+ - Default `DB_HOST`: `127.0.0.1`
20
+ - Default `DB_PORT`: `3306`
21
+ - Default `DB_DATABASE`: `rails`
22
+ - Default `DB_USERNAME`: `root`
23
+
24
+ ## Resources
25
+
26
+ ```json genesis-resource
27
+ {
28
+ "id": "database",
29
+ "kind": "mysql",
30
+ "environmentAlternatives": [
31
+ {
32
+ "bindings": {
33
+ "database": "DB_DATABASE",
34
+ "host": "DB_HOST",
35
+ "password": "DB_PASSWORD",
36
+ "port": "DB_PORT",
37
+ "username": "DB_USERNAME"
38
+ },
39
+ "allowEmpty": ["password"],
40
+ "preferred": true
41
+ }
42
+ ]
43
+ }
44
+ ```
45
+
46
+ ## Guidance
47
+
48
+ - `rails new -d mysql` (adapter `mysql2`) or `-d trilogy` hard-codes database
49
+ names. Make `config/database.yml` read the resource names: under `default`,
50
+ `host: <%= ENV.fetch("DB_HOST", "127.0.0.1") %>`,
51
+ `port: <%= ENV.fetch("DB_PORT", 3306) %>`,
52
+ `username: <%= ENV["DB_USERNAME"] %>`, `password: <%= ENV["DB_PASSWORD"] %>`;
53
+ and `database: <%= ENV["DB_DATABASE"] %>` for development and the
54
+ production primary. Keep `test` on its own disposable database name.
55
+ - Keep `encoding: utf8mb4`. `mysql2` compiles against the MySQL client
56
+ library; `trilogy` (Rails 7.1+) is pure Ruby and avoids it. Do not switch an
57
+ existing app's adapter without testing it.
58
+ - `bin/rails test` purges and recreates the test database, which needs
59
+ `CREATE`/`DROP` privileges unless the test database is supplied and
60
+ disposable.
61
+ - Rails 8 production declares separate `cache`, `queue` and `cable`
62
+ databases. When only one database is supplied, follow the Solid Cache, Solid
63
+ Queue and Solid Cable single-database instructions (their schemas become
64
+ ordinary migrations and their `connects_to` settings are removed) instead of
65
+ inventing extra database names.
66
+ - Use the inherited Rails migration and seed guidance. Keep connection,
67
+ integration and payment records in this database through Active Record
68
+ migrations and transactions; test uniqueness and concurrent updates on MySQL
69
+ itself.
70
+
71
+ ## Adoption
72
+
73
+ - Confirm the adapter, every environment's database, username, password, host
74
+ and port expressions in `config/database.yml`, and whether `DATABASE_URL` is
75
+ read, before declaring readiness or connecting. Align the project Resource
76
+ bindings with the names the file actually reads.
@@ -0,0 +1,74 @@
1
+ # Stack piece: rails-postgresql
2
+
3
+ ## Description
4
+
5
+ Rails PostgreSQL connection, Active Record migration, and database environment conventions.
6
+
7
+ ## Requires
8
+
9
+ - `rails`
10
+ - `postgresql`
11
+
12
+ ## Conflicts
13
+
14
+ - `rails-mysql`
15
+ - `rails-sqlite`
16
+
17
+ ## Environment defaults
18
+
19
+ - Default `DB_HOST`: `127.0.0.1`
20
+ - Default `DB_PORT`: `5432`
21
+ - Default `DB_DATABASE`: `rails`
22
+ - Default `DB_USERNAME`: `postgres`
23
+
24
+ ## Resources
25
+
26
+ ```json genesis-resource
27
+ {
28
+ "id": "database",
29
+ "kind": "postgresql",
30
+ "environmentAlternatives": [
31
+ {
32
+ "bindings": {
33
+ "database": "DB_DATABASE",
34
+ "host": "DB_HOST",
35
+ "password": "DB_PASSWORD",
36
+ "port": "DB_PORT",
37
+ "username": "DB_USERNAME"
38
+ },
39
+ "allowEmpty": ["password"],
40
+ "preferred": true
41
+ }
42
+ ]
43
+ }
44
+ ```
45
+
46
+ ## Guidance
47
+
48
+ - `rails new -d postgresql` hard-codes database names and reads only a
49
+ production password variable. Make `config/database.yml` read the resource
50
+ names: under `default`, `host: <%= ENV.fetch("DB_HOST", "127.0.0.1") %>`,
51
+ `port: <%= ENV.fetch("DB_PORT", 5432) %>`,
52
+ `username: <%= ENV["DB_USERNAME"] %>`, `password: <%= ENV["DB_PASSWORD"] %>`;
53
+ and `database: <%= ENV["DB_DATABASE"] %>` for development and the
54
+ production primary. Keep `test` on its own disposable database name.
55
+ - `bin/rails test` purges and recreates the test database, which needs the
56
+ `CREATEDB` privilege unless the test database is supplied and disposable.
57
+ - Rails 8 production declares separate `cache`, `queue` and `cable`
58
+ databases. When only one database is supplied, follow the Solid Cache, Solid
59
+ Queue and Solid Cable single-database instructions (their schemas become
60
+ ordinary migrations and their `connects_to` settings are removed) instead of
61
+ inventing extra database names.
62
+ - The `pg` gem compiles against libpq unless the locked version ships a
63
+ precompiled gem for the platform.
64
+ - Use the inherited Rails migration and seed guidance. Keep connection,
65
+ integration and payment records in this database through Active Record
66
+ migrations and transactions; test uniqueness and concurrent updates on
67
+ PostgreSQL itself.
68
+
69
+ ## Adoption
70
+
71
+ - Confirm the adapter, every environment's database, username, password, host
72
+ and port expressions in `config/database.yml`, and whether `DATABASE_URL` is
73
+ read, before declaring readiness or connecting. Align the project Resource
74
+ bindings with the names the file actually reads.
@@ -0,0 +1,60 @@
1
+ # Stack piece: rails-sqlite
2
+
3
+ ## Description
4
+
5
+ Rails SQLite connection, Active Record migration, and database filename conventions.
6
+
7
+ ## Requires
8
+
9
+ - `rails`
10
+ - `sqlite`
11
+
12
+ ## Conflicts
13
+
14
+ - `rails-mysql`
15
+ - `rails-postgresql`
16
+
17
+ ## Resources
18
+
19
+ ```json genesis-resource
20
+ {
21
+ "id": "database",
22
+ "kind": "sqlite",
23
+ "environmentAlternatives": [
24
+ {
25
+ "bindings": {
26
+ "database": "DB_DATABASE"
27
+ },
28
+ "preferred": true
29
+ }
30
+ ]
31
+ }
32
+ ```
33
+
34
+ ## Guidance
35
+
36
+ - `rails new` (SQLite is the default) writes repository-relative files under
37
+ `storage/`, and Rails 8.1 leaves the production files unset. Make the
38
+ development and production primary read the supplied filename with the
39
+ generated name as fallback, for example
40
+ `database: <%= ENV.fetch("DB_DATABASE", "storage/development.sqlite3") %>`.
41
+ A bare `ENV.fetch("DB_DATABASE")` raises while `database.yml` loads and
42
+ breaks generators and asset builds that run without the variable. Keep `test`
43
+ on its own file such as `storage/test.sqlite3`.
44
+ - Rails 8 production also declares `cache`, `queue` and `cable` SQLite
45
+ databases. Keep them next to the primary file, for example
46
+ `<%= File.join(File.dirname(ENV.fetch("DB_DATABASE", "storage/production.sqlite3")), "production_cache.sqlite3") %>`,
47
+ so they persist with it; never leave them in a disposable release directory.
48
+ - Do not replace a supplied filename with a repository-relative default or
49
+ delete an existing file. `bin/rails db:prepare` creates a missing file and
50
+ its schema and migrates an existing one.
51
+ - The `sqlite3` gem normally installs a precompiled native gem; a source build
52
+ needs the SQLite headers. Use the inherited Rails migration and seed
53
+ guidance and test concurrent writes on SQLite itself.
54
+
55
+ ## Adoption
56
+
57
+ - Read `config/database.yml` for every environment's filename, including the
58
+ Rails 8 cache, queue and cable files, and preserve existing data: snapshot
59
+ it before moving to a supplied filename. Do not switch an existing app to an
60
+ empty database.
@@ -0,0 +1,161 @@
1
+ # Stack piece: rails
2
+
3
+ ## Description
4
+
5
+ Ruby on Rails application, Bundler, Active Record, Action Pack, assets, and
6
+ framework lifecycle conventions. Identified by `Gemfile.lock` listing `rails`,
7
+ `bin/rails`, `config/application.rb`, and `config/database.yml`.
8
+ Authoritative framework documentation: https://guides.rubyonrails.org/
9
+
10
+ ## Requires
11
+
12
+ - `ruby`
13
+
14
+ ## Guidance
15
+
16
+ - Use the Rails version locked in `Gemfile.lock` and its matching guides and
17
+ API documentation. Preserve Rails conventions (MVC, Active Record, concerns,
18
+ jobs, mailers, generators, `bin/rails` tasks) instead of adding parallel
19
+ framework plumbing.
20
+ - The development server binds the supplied host and port:
21
+ `bin/rails server -b <host> -p <port>`. Without `-p` Rails reads `PORT`;
22
+ it never reads `HOST` (only `BINDING`, and production defaults to
23
+ `0.0.0.0`), so pass `-b` explicitly. A server reachable only on loopback
24
+ is what makes trusting proxy headers safe.
25
+ - Behind a loopback development reverse proxy that rewrites `Host` and sends
26
+ `X-Forwarded-Host`, `X-Forwarded-Proto` and `X-Forwarded-Port`, Rails derives
27
+ `request.host`, `request.base_url` and generated URLs from those headers
28
+ natively (loopback is a trusted proxy by default). Do not hard-code
29
+ `default_url_options` hosts for development.
30
+ - Host authorization then sees the browser-facing host and answers "Blocked
31
+ hosts". In development, list that host (or `.parent.domain`) in
32
+ `RAILS_DEVELOPMENT_HOSTS`, or, when the server binds only loopback, add
33
+ `config.hosts.clear` to `config/environments/development.rb` only. In
34
+ production set `config.hosts` explicitly from the environment and exclude the
35
+ health route:
36
+ `config.host_authorization = { exclude: ->(request) { request.path == "/up" } }`.
37
+ - CSRF compares the `Origin` header with `request.base_url`. Some development
38
+ proxies rewrite a same-origin `Origin` to the upstream loopback address while
39
+ forwarding the browser host; form posts then fail with "HTTP Origin header
40
+ ... didn't match request.base_url". Only in that case, and only in
41
+ `development.rb`, set
42
+ `config.action_controller.forgery_protection_origin_check = false`; the
43
+ authenticity token still protects forms. Action Cable compares origins the
44
+ same way: allow the observed development origin in
45
+ `config.action_cable.allowed_request_origins` rather than disabling its
46
+ forgery protection.
47
+ - Secrets: development uses `tmp/local_secret.txt`. Production needs
48
+ `SECRET_KEY_BASE` (generate with `bin/rails secret`) or `RAILS_MASTER_KEY`
49
+ for `config/credentials.yml.enc`, supplied through the deployment
50
+ environment, never committed. `assets:precompile` in production also aborts
51
+ without it; a build that must not see the real secret can use
52
+ `SECRET_KEY_BASE_DUMMY=1`. When an
53
+ imported app lacks `config/master.key`, never run `bin/rails credentials:edit`
54
+ or delete the encrypted file to "fix" it: that destroys the existing values.
55
+ Ask for the key or move the needed values to environment variables.
56
+ - `bin/rails db:prepare` creates the database, loads the schema and runs
57
+ `db/seeds.rb` when it is new, and migrates it otherwise, so repeated setup is
58
+ safe. Seeds must be idempotent (`find_or_create_by!`). Commit generated
59
+ migrations and `db/schema.rb`; never run `db:reset`, `db:setup`,
60
+ `db:schema:load`, `db:drop` or edit an applied migration as routine setup.
61
+ - `DATABASE_URL` overrides the connection of every environment, including
62
+ `test`. Keep it unset where tests run, and point `test` in
63
+ `config/database.yml` at its own disposable database (a supplied disposable
64
+ test database name when the environment declares one), never at the
65
+ development or production database. `bin/rails test` recreates the test
66
+ schema.
67
+ - Mode is set per environment: `RAILS_ENV=production` belongs in the
68
+ production environment and its commands, never in a project-wide default.
69
+ - Assets: never commit `public/assets`; a stale local `public/assets` shadows
70
+ development changes. Propshaft/Sprockets serve sources in development;
71
+ `tailwindcss-rails`, `cssbundling-rails` and `jsbundling-rails` need their
72
+ build or watcher (`bin/dev` runs them from `Procfile.dev`). When the Develop
73
+ command becomes `bin/dev`, confirm its web process still binds loopback and
74
+ the supplied `PORT`. Rails before 7.1 needs `RAILS_SERVE_STATIC_FILES=1` in
75
+ production without a front web server.
76
+ - Native gems need a C toolchain and headers: `psych` needs libyaml, `pg`
77
+ needs libpq, `mysql2` needs the MySQL client library, `sqlite3` usually ships
78
+ a precompiled gem. Dependency installation therefore also uses `cpp`.
79
+ `trilogy` avoids the MySQL client library. A `Gemfile.lock` resolved only on
80
+ another platform needs `bundle lock --add-platform x86_64-linux` (or the
81
+ deployment platform) before frozen deployment installs.
82
+ - Production: `bin/rails server -e production` reads `PORT`; bind loopback
83
+ with `-b`. Rails 8 enables `assume_ssl`/`force_ssl`; with `force_ssl` but no
84
+ `assume_ssl`, exclude `/up` from the redirect:
85
+ `config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }`.
86
+ Rails 8 runs Solid Queue jobs inside Puma only with `SOLID_QUEUE_IN_PUMA=1`
87
+ in the production environment; otherwise run `bin/jobs` as its own process.
88
+ - Keep the `/up` health route (`rails/health#show`, Rails 7.1+) unauthenticated.
89
+ Older apps add an equivalent route and update the Outputs and Deployment
90
+ readiness.
91
+ - Login: Rails 8 `bin/rails generate authentication`, Devise or the app's own
92
+ `has_secure_password`. Seed one administrator (an `admin` boolean or role)
93
+ and one ordinary user idempotently in `db/seeds.rb` for development only,
94
+ with passwords from the environment; never seed production credentials.
95
+ - The JavaScript dependency step assumes npm. A `yarn.lock` or `bun.lockb`
96
+ means that line uses the matching tool; importmap apps have no
97
+ `package.json` and skip it.
98
+
99
+ ## Adoption
100
+
101
+ - Read `Gemfile`, `Gemfile.lock` (Rails and Ruby versions, database adapter
102
+ gem, asset and JavaScript tooling), `config/database.yml`,
103
+ `config/environments/*.rb`, `config/puma.rb`, `Procfile.dev`/`bin/dev`,
104
+ `config/routes.rb` (health route) and whether `config/master.key` or
105
+ `config/credentials/*.key` exist before changing project contracts.
106
+ - Replace each proposed setup, Outputs, Verification and Deployment line that
107
+ does not match the app: RSpec apps verify with `bundle` `exec` `rspec`;
108
+ API-only apps have no `assets:precompile`; a different health route changes
109
+ both readiness lines; a different JavaScript package manager changes the
110
+ install step.
111
+ - Select the matching database integration (`rails-postgresql`,
112
+ `rails-mysql` or `rails-sqlite`) and align `config/database.yml` with its
113
+ environment names. Preserve existing data and the credentials file.
114
+
115
+ ## Workspace setup
116
+
117
+ - Prepare `Install Ruby dependencies` with `ruby` `cpp` when `Gemfile` exists: `bundle` `install`
118
+ - Prepare `Install JavaScript dependencies` with `nodejs` if `package.json` exists: `npm` `install`
119
+ - Prepare `Prepare database` with `ruby` when `bin/rails` exists: `bin/rails` `db:prepare`
120
+
121
+ ## Outputs
122
+
123
+ ### Target `app`: Run Rails app
124
+
125
+ - Default.
126
+ - Mode: `interactive`
127
+ - Runtimes: `ruby`
128
+ - Run `Develop`: `bin/rails` `server` `-b` `{host}` `-p` `{port}`
129
+
130
+ #### Presentation
131
+
132
+ - Kind: `web`
133
+ - Preferred port: `3000`
134
+ - URL path: `/`
135
+ - Ready when: `GET` `/up` returns `200`
136
+
137
+ ## Verification
138
+
139
+ - Verify `application`: `bin/rails` `test`
140
+
141
+ ## Deployment
142
+
143
+ - Runtimes: `ruby` `cpp`
144
+ - Recreate on restore: `vendor/bundle` `node_modules` `tmp` `log`
145
+ - Ready when: `GET` `/up` returns `200`
146
+ - Prepare `Use deployment bundle`: `bundle` `config` `set` `--local` `deployment` `true`
147
+ - Prepare `Exclude development gems`: `bundle` `config` `set` `--local` `without` `development test`
148
+ - Prepare `Install Ruby dependencies`: `bundle` `install`
149
+ - Build `Precompile assets`: `bin/rails` `assets:precompile` `RAILS_ENV=production`
150
+ - Migrate `Prepare database`: `bin/rails` `db:prepare` `RAILS_ENV=production`
151
+ - Serve `Start`: `bin/rails` `server` `-e` `production` `-b` `127.0.0.1`
152
+
153
+ ## Deslop
154
+
155
+ - Preserve Rails conventions: models, concerns, controllers, callbacks,
156
+ validations, strong parameters, jobs, mailers and routes stay where Rails
157
+ expects them.
158
+ - Remove service objects, decorators or wrappers that only forward to Active
159
+ Record or Action Pack without protecting a real application seam.
160
+ - Preserve migration history, `db/schema.rb`, credentials and seed
161
+ idempotence; cleanup is not permission for destructive schema changes.
@@ -45,10 +45,7 @@ Ruby module, class, callable, dependency, lifecycle, and test conventions.
45
45
  only git sources. Verify that each spec loads from its source root.
46
46
  - Running a web process: bind the supplied listen host and port, trust forwarded
47
47
  headers only from a loopback proxy, and read secrets from the environment.
48
- Rails: allow the served host and the proxy's loopback host in `config.hosts`
49
- (Rails honours `X-Forwarded-Host`), read `SECRET_KEY_BASE` from the
50
- environment (generate it with `bin/rails secret`), and use
51
- `bin/rails db:prepare` for setup.
48
+ For Rails select `rails`; its piece owns the framework traps.
52
49
 
53
50
  ## Connected development
54
51
 
@@ -0,0 +1,74 @@
1
+ # Stack piece: spring-boot-mysql
2
+
3
+ ## Description
4
+
5
+ Spring Boot MySQL or MariaDB datasource, JDBC driver, Flyway, JPA, and database
6
+ environment conventions.
7
+
8
+ ## Requires
9
+
10
+ - `spring-boot`
11
+ - `mysql`
12
+
13
+ ## Conflicts
14
+
15
+ - `spring-boot-postgresql`
16
+
17
+ ## Environment defaults
18
+
19
+ - Default `DB_HOST`: `127.0.0.1`
20
+ - Default `DB_PORT`: `3306`
21
+ - Default `DB_NAME`: `spring`
22
+ - Default `DB_USERNAME`: `root`
23
+
24
+ ## Resources
25
+
26
+ ```json genesis-resource
27
+ {
28
+ "id": "database",
29
+ "kind": "mysql",
30
+ "environmentAlternatives": [
31
+ {
32
+ "bindings": {
33
+ "database": "DB_NAME",
34
+ "host": "DB_HOST",
35
+ "password": "DB_PASSWORD",
36
+ "port": "DB_PORT",
37
+ "username": "DB_USERNAME"
38
+ },
39
+ "allowEmpty": ["password"],
40
+ "preferred": true
41
+ }
42
+ ],
43
+ "optionalBindings": {
44
+ "testDatabase": "TEST_DB_NAME"
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Guidance
50
+
51
+ - Compose the JDBC URL from the individual names in `application.properties`:
52
+ `spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}`,
53
+ `spring.datasource.username=${DB_USERNAME}` and
54
+ `spring.datasource.password=${DB_PASSWORD:}`. A `mysql://` connection URL is
55
+ not a JDBC URL; do not feed one to `spring.datasource.url`.
56
+ - Match the driver to the server: check `SELECT VERSION()`. MySQL uses the
57
+ `com.mysql:mysql-connector-j` runtime driver. A MariaDB server needs
58
+ `org.mariadb.jdbc:mariadb-java-client` with a `jdbc:mariadb://` URL;
59
+ `mysql-connector-j` can fail against current MariaDB while Hibernate reads
60
+ connection metadata ("Unable to determine Dialect"). Flyway 10 and later
61
+ also need `org.flywaydb:flyway-mysql`, which covers both servers.
62
+ - Create databases with `utf8mb4`.
63
+ - When `TEST_DB_NAME` is supplied, the `test` profile's
64
+ `src/test/resources/application-test.properties` sets
65
+ `spring.datasource.url` to the same JDBC URL with `${TEST_DB_NAME}` in place
66
+ of `${DB_NAME}`. Flyway migrates that existing database; the database user
67
+ may lack permission to create databases. Never point tests at `DB_NAME`.
68
+
69
+ ## Adoption
70
+
71
+ - Confirm the server (MySQL or MariaDB), the datasource properties, the
72
+ environment names they read, the driver and Flyway or Liquibase modules, and
73
+ every profile's overrides from source before declaring readiness or
74
+ connecting to the database.