Table of contents
WordsEnigma: A word game across Redwood and Prisma
WordsEnigma is a fork with separate Redwood web and API workspaces. Its data model links users, languages, word banks, games and individual guesses. GraphQL services translate application operations into Prisma database calls.
- Languages
- 6Code breakdown
- Documented components
- 2Explore modules
- Source documents
- 2Read the instructions
Repository languagesTypeScript 97.12%6
Shares calculated from GitHub Linguist bytes.
| Language | % | Bytes |
|---|---|---|
| TypeScript | 487,080 | |
| CSS | 11,156 | |
| JavaScript | 2,001 | |
| Dockerfile | 807 | |
| HTML | 364 | |
| Shell | 125 |
1. Overview
1.1. Why it exists
TypeScript dictionary validation and game solver engine supporting multiple languages and word lengths.
1.2. Best fit
Algorithmic word game logic and solver heuristics.
2. Use cases
RedwoodJS prototype of a multi-language Wordle, with a French word board, GraphQL API and admin CRUD on PostgreSQL.
- Guess a five-letter word
- Player
The /phil page (MotDuJourPhilPage/App.tsx) gives six tries on a 6×5 grid, rejects words missing from the French list in data/fr.ts and colours letters and keyboard keys; the solution is hard-coded to GRAND.
- Create an account
- Player
/signup, /login, /forgot-password and /reset-password use Redwood dbAuth (api/src/functions/auth.ts) against the User model with hashed password and salt.
- Manage words and word banks
- Administrator
Routes under /admin, wrapped in Private roles="admin", give scaffolded CRUD pages for users, languages, words, word banks, games, try rows, letters and statistics through the GraphQL SDL services.
- Seed French words
- AdministratorOnline dictionaries
yarn seed runs scripts/seed.ts, which upserts languages and the fr word bank, then fetches definitions from fr.wiktionary.org or le-dictionnaire.com with the cheerio crawler before inserting words.
- Track games and streaks
- Player
The Prisma schema stores each Game with its TryRow and Letter records and a Statistic row per user (games played, won, lost, streak, average); the data model is in place but the play pages do not write to it yet.
2.1. Scenario: Run the French board locally
- Start PostgreSQL with docker run --name=db -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=admin -p 5432:5432 -d postgres, as in the root README.
- In WordsEnigma/, run yarn install, then yarn rw prisma migrate dev to apply api/db/migrations.
- Run yarn seed to load the languages, the fr word bank and the words.
- Start yarn redwood dev and open http://localhost:8910/phil.
- Type five letters, press Enter and read the colours until the word is found or the six rows are used.
Files readREADME.mdWordsEnigma/README.mdWordsEnigma/package.jsonWordsEnigma/api/db/schema.prismaWordsEnigma/web/src/Routes.tsxWordsEnigma/web/src/pages/MotDuJourPhilPage/App.tsxWordsEnigma/scripts/seed.tsWordsEnigma/scripts/words/dictionnaryCrawler/fr.tsWordsEnigma/docker-compose.yml
3. Getting started
These commands come from the repository documentation. They were not run during this review.
Tasks declared in manifests
4. Repository references
Excerpts from the repository’s guides, in their original language. Links open the inspected source revision.
Development and contributions
4.1. Testing with Jest
WordsEnigma/README.md
5. Features and components 2
- Data relationships
- schema.prisma uses PostgreSQL. A Game belongs to a user and word, references a word bank, and has try rows. Language records connect words and user settings, so multilingual behavior has a stored data model.
- Services and persistence
- games.ts exposes list, read, create, update and delete resolvers using db.game. Relation resolvers fetch the associated user, word, bank and guesses. This layer keeps GraphQL operations close to the persistence model.
6. Architecture
Expand a component to follow its connections, or explore the full diagram.
Redwood web UI
- To GraphQL API
GraphQL API
Game service resolvers
- From GraphQL API
- To Prisma client
Prisma client
PostgreSQL relations
- From Prisma client
Mermaid Interactive diagram
System overview of the components and connections verified in the repository.

flowchart LR
n0["Redwood web UI"]
n1["GraphQL API"]
n2["Game service resolvers"]
n3["Prisma client"]
n4["PostgreSQL relations"]
n0 --> n1
n1 --> n2
n2 --> n3
n3 --> n4
Text version of the diagram
- Redwood web UI → GraphQL API
- GraphQL API → Game service resolvers
- Game service resolvers → Prisma client
- Prisma client → PostgreSQL relations
Follow one path through the code
Follow the game resolver into findUnique, then its relation resolvers into the linked records. These generic CRUD methods do not by themselves explain guess validation or prove that a user can access only their own games.
7. Technical dossier
Built from the source at commit a656449 (227 files). Each item comes from a pattern match in the code, so open the linked file before relying on it.
7.1. Layers and modules
Folders are sorted into layers by name, from the user interface down to data access. Because the sorting uses names only, the diagram says nothing about calls between layers.
Mermaid Layered view
flowchart TB
subgraph L_presentation["Presentation"]
direction TB
presentation_0["WordsEnigma/web<br/>142 files"]
end
subgraph L_interface["Entry points and API"]
direction TB
interface_0["WordsEnigma/api<br/>15 files"]
end
subgraph L_application["Application services"]
direction TB
application_0["WordsEnigma/api<br/>18 files"]
application_1["WordsEnigma/scripts<br/>11 files"]
end
subgraph L_domain["Domain and business rules"]
direction TB
domain_0["WordsEnigma/web<br/>13 files"]
end
subgraph L_infrastructure["Data and infrastructure"]
direction TB
infrastructure_0["WordsEnigma/api<br/>3 files"]
infrastructure_1["WordsEnigma/scripts<br/>1 file"]
infrastructure_2["WordsEnigma/web<br/>1 file"]
end
subgraph L_core["Core source"]
direction TB
core_0["WordsEnigma<br/>3 files"]
end
subgraph L_tests["Tests"]
direction TB
tests_0["WordsEnigma<br/>17 files"]
end
subgraph L_hosting["Build, CI and hosting"]
direction TB
hosting_0["WordsEnigma<br/>4 files"]
hosting_1[".github<br/>1 file"]
end
L_presentation ~~~ L_interface
L_interface ~~~ L_application
L_application ~~~ L_domain
L_domain ~~~ L_infrastructure
L_infrastructure ~~~ L_core
L_core ~~~ L_tests
L_core ~~~ L_hosting
| Module | Layer | Files | Types | Extensions |
|---|---|---|---|---|
WordsEnigma/web | Presentation | 156 | 18 | .tsx .css .js |
WordsEnigma/api | Application services | 36 | 0 | .ts .js |
WordsEnigma/scripts | Application services | 12 | 0 | .ts |
WordsEnigma | Core source | 3 | 0 | .js |
7.2. C4 model
From system context to code declarations. Each level reflects the available source evidence.
UML 1 · System context
The widest C4 view: who uses the project and which outside systems and data stores it relies on. Rendered with uml-mcp.
PlantUML source
@startuml
!include <C4/C4_Context>
LAYOUT_LEFT_RIGHT()
System(SYS, "WordsEnigma", "WordsEnigma is a fork with separate Redwood web and API workspaces")
SystemDb(D0, "Prisma")
Rel(SYS, D0, "Reads and writes")
@enduml
UML 2 · Containers
One level closer: the parts that run separately inside the project, their main language and how calls flow between them. Rendered with uml-mcp.
PlantUML source
@startuml
!include <C4/C4_Container>
LAYOUT_LEFT_RIGHT()
System_Boundary(SYS, "WordsEnigma") {
Container(C0, "db", "Docker")
Container(C1, "web", "Docker")
Container(C2, "api", "Docker")
ContainerDb(DB0, "Prisma", "")
}
Rel(C0, DB0, "Reads and writes")
@enduml
UML 3 · Components and layers
Modules grouped by source-layer classification. Boundaries show organization, not runtime isolation or call relationships. Rendered with uml-mcp.
PlantUML source
@startuml
!include <C4/C4_Component>
LAYOUT_TOP_DOWN()
System_Boundary(SYS, "WordsEnigma") {
Boundary(L0, "Presentation", "layer") {
Component(M0_0, "WordsEnigma/web", "React, .css, JavaScript", "142 files")
}
Boundary(L1, "Entry points and API", "layer") {
Component(M1_0, "node_modules/cheerio", "TypeScript, JavaScript", "20 files")
Component(M1_1, "WordsEnigma/api", "TypeScript, JavaScript", "15 files")
Component(M1_2, "node_modules/parse5", "JavaScript", "8 files")
Component(M1_3, "node_modules/parse5-htmlparser2-tree-adapter", "JavaScript", "2 files")
Component(M1_4, "node_modules/asynckit", "JavaScript", "1 files")
Component(M1_5, "node_modules/axios", "JavaScript", "1 files")
Component(M1_6, "node_modules/boolbase", "JavaScript", "1 files")
Component(M1_7, "node_modules/follow-redirects", "JavaScript", "1 files")
Component(M1_more, "+2 modules", "", "")
}
Boundary(L2, "Application services", "layer") {
Component(M2_0, "WordsEnigma/api", "TypeScript", "18 files")
Component(M2_1, "WordsEnigma/scripts", "TypeScript", "11 files")
}
Boundary(L3, "Domain and business rules", "layer") {
Component(M3_0, "WordsEnigma/web", "React, .css", "13 files")
Component(M3_1, "node_modules/axios", "JavaScript", "8 files")
Component(M3_2, "node_modules/parse5", "JavaScript", "2 files")
}
Boundary(L4, "Data and infrastructure", "layer") {
Component(M4_0, "node_modules/css-select", "TypeScript, JavaScript", "44 files")
Component(M4_1, "node_modules/cheerio", "TypeScript, JavaScript", "40 files")
Component(M4_2, "node_modules/domutils", "TypeScript, JavaScript", "32 files")
Component(M4_3, "node_modules/entities", "TypeScript, JavaScript", "32 files")
Component(M4_4, "node_modules/axios", "JavaScript", "26 files")
Component(M4_5, "node_modules/css-what", "TypeScript, JavaScript", "16 files")
Component(M4_6, "node_modules/htmlparser2", "TypeScript, JavaScript", "16 files")
Component(M4_7, "node_modules/cheerio-select", "TypeScript, JavaScript", "12 files")
Component(M4_more, "+11 modules", "", "")
}
Boundary(L5, "Core source", "layer") {
Component(M5_0, "node_modules/parse5", "TypeScript, JavaScript", "50 files")
Component(M5_1, "node_modules/asynckit", "JavaScript", "5 files")
Component(M5_2, "WordsEnigma", "JavaScript", "3 files")
Component(M5_3, "node_modules/axios", "JavaScript, TypeScript", "3 files")
Component(M5_4, "node_modules/follow-redirects", "JavaScript", "3 files")
Component(M5_5, "node_modules/parse5-htmlparser2-tree-adapter", "TypeScript", "2 files")
Component(M5_6, "node_modules/form-data", "TypeScript", "1 files")
}
Boundary(L6, "Tests", "layer") {
Component(M6_0, "WordsEnigma", "TypeScript, React", "17 files")
}
Boundary(L7, "Build, CI and hosting", "layer") {
Component(M7_0, "WordsEnigma", "Dockerfile, .yml, .conf", "4 files")
Component(M7_1, ".github", ".yml", "1 files")
Component(M7_2, "node_modules", "Makefile", "1 files")
}
}
@enduml
UML 4 · Code
Selected declarations, fields and methods grouped by source file. No inheritance or call edges are inferred. Rendered with uml-mcp.
PlantUML source
@startuml
skinparam backgroundColor transparent
skinparam shadowing false
skinparam roundCorner 10
skinparam defaultFontName Arial
skinparam defaultFontSize 13
skinparam ArrowColor #4e6070
skinparam ArrowFontColor #3d4f5f
skinparam titleFontSize 14
skinparam actorBorderColor #006a62
skinparam actorBackgroundColor #e9f3f4
skinparam usecaseBorderColor #006a62
skinparam usecaseBackgroundColor #e9f3f4
skinparam componentBorderColor #006a62
skinparam componentBackgroundColor #e9f3f4
skinparam interfaceBorderColor #006a62
skinparam interfaceBackgroundColor #ffffff
skinparam nodeBorderColor #4e6070
skinparam nodeBackgroundColor #f4f8fb
skinparam databaseBorderColor #006a62
skinparam databaseBackgroundColor #ffffff
skinparam cloudBorderColor #4e6070
skinparam cloudBackgroundColor #f0f5fa
skinparam artifactBorderColor #006a62
skinparam artifactBackgroundColor #ffffff
skinparam rectangleBorderColor #b0c2d3
skinparam activityBorderColor #006a62
skinparam activityBackgroundColor #e9f3f4
skinparam partitionBorderColor #b0c2d3
skinparam stereotypeCBackgroundColor #ffffff
top to bottom direction
hide empty members
package "WordsEnigma" {
package "WordsEnigma/.yarn/releases/yarn-3.2.1.cjs" as F0 {
class "w6" as T0_0 {
bufferLength()
encoding()
setEncoding()
objectMode()
write()
read()
}
class "e" as T0_1 {
submit()
create()
}
}
package "WordsEnigma/web/src/pages/MotduJourPage/subcomponents/GameBoard/GameBoard.tsx" as F1 {
class "IState" as T1_0 {
motEssayer
motResultat
nbMotJouer
gagner
banqueDeMots
grandeBanqueMots
motDuJour
currentRow
}
class "IProps" as T1_1 {
cols
rows
}
}
package "WordsEnigma/web/src/pages/MotduJourPage/subcomponents/Rules/Rules.tsx" as F2 {
class "IProps" as T2_0 {
Rules
}
class "IState" as T2_1 {
Rules
}
}
package "WordsEnigma/web/src/pages/MotduJourPage/subcomponents/Header/Header.tsx" as F3 {
class "IProps" as T3_0 {
title
}
class "IState" as T3_1 {
Header
}
}
package "WordsEnigma/web/src/pages/MotduJourPage/subcomponents/Share/Share.tsx" as F4 {
class "IProps" as T4_0 {
Share
}
class "IState" as T4_1 {
Share
}
}
package "WordsEnigma/web/src/pages/MotduJourPage/subcomponents/Success/Success.tsx" as F5 {
class "IProps" as T5_0 {
Success
}
class "IState" as T5_1 {
Success
}
}
package "WordsEnigma/web/src/pages/MotduJourPage/subcomponents/Keyboard/Keyboard.tsx" as F6 {
class "IProps" as T6_0 {
}
class "IState" as T6_1 {
}
}
}
@enduml
7.3. Entities and data model 12
Mermaid Entity class diagram
classDiagram
direction LR
class E0["IState"] {
}
class E1["IProps"] {
}
An arrow links a field to the entity its type names.
| Entity | Kind | First fields |
|---|---|---|
IState | Record or interface | motEssayer, motResultat, nbMotJouer, gagner, banqueDeMots, grandeBanqueMots, motDuJour, currentRow |
IProps | Record or interface | cols, rows |
IProps | Record or interface | Rules |
IState | Record or interface | Rules |
IProps | Record or interface | title |
IProps | Record or interface | Share |
IProps | Record or interface | Success |
IState | Record or interface | Header |
7.4. Business logic
Once UI code and the services and entities above are set aside, these classes have the most methods.
7.5. Database and persistence
Tables and collections 9
User UserSetting Language Word WordBank Game Letter TryRow Statistic
Data containers
7.6. External integrations
HTTP clients
Hosts named in the code
fr.wiktionary.org1 filesWordsEnigma/scripts/words/dictionnaryCrawler/fr.ts:6www.le-dictionnaire.com1 filesWordsEnigma/scripts/words/dictionnaryCrawler/fr.ts:5
7.7. Stack and dependencies
Node.js WordsEnigma/api/package.json 2 runtime
Node.js WordsEnigma/web/package.json 7 runtime
External dependencies
13 declared packages (11 runtime, 2 development) in WordsEnigma/package.json, WordsEnigma/api/package.json, WordsEnigma/web/package.json.
Package table 13
| Package | Version | Scope | Purpose | Registry |
|---|---|---|---|---|
axios | ^0.27.2 | runtime | HTTP client | npmjs.com |
cheerio | ^1.0.0-rc.12 | runtime | Scraping and parsing | npmjs.com |
@getbigger-io/prisma-fixtures-cli | ^1.0.10 | development | Database access | npmjs.com |
@redwoodjs/core | 1.5.2 | development | Foundational packages and config required to build RedwoodJS. | npmjs.com |
@redwoodjs/api | 1.5.2 | runtime | — | npmjs.com |
@redwoodjs/graphql-server | 1.5.2 | runtime | — | npmjs.com |
@redwoodjs/auth | 1.5.2 | runtime | — | npmjs.com |
@redwoodjs/forms | 1.5.2 | runtime | — | npmjs.com |
@redwoodjs/router | 1.5.2 | runtime | — | npmjs.com |
@redwoodjs/web | 1.5.2 | runtime | — | npmjs.com |
prop-types | 15.8.1 | runtime | Runtime type checking for React props and similar objects. | npmjs.com |
react | 17.0.2 | runtime | User interface | npmjs.com |
react-dom | 17.0.2 | runtime | User interface | npmjs.com |
7.8. CI/CD pipeline
1 GitHub Actions workflow, 1 job. Each box is a job; double-bordered boxes publish or deploy, and arrows follow needs.
Mermaid Pipeline flow
flowchart LR
subgraph wf0["CI"]
direction LR
wf0_build["build<br/>ubuntu-latest"]
end
t0(["Triggers · the · workflow · on · push · or"])
t0 --> wf0_build
| Workflow | Triggers | Jobs | Publishes to |
|---|---|---|---|
CI.github/workflows/main.yml | Triggers, the, workflow, on, push, or |
| — |
7.9. Deployment
Mermaid Deployment diagram
flowchart LR
repo[("GitHub repository")]
ci[["GitHub Actions<br/>1 workflow"]]
image["Docker image<br/>FROM node:16-alpine"]
subgraph compose["Docker Compose"]
svc_db["db"]
svc_web["web"]
svc_api["api"]
end
repo -->|"push or pull request"| ci
ci -->|"docker build"| image
image -->|"docker compose up"| compose
UML Deployment
The outer node is where the code runs. Each base image points to what it builds, solid arrows lead to databases and dashed ones to outside services. Rendered with uml-mcp.
PlantUML source
@startuml
skinparam backgroundColor transparent
skinparam shadowing false
skinparam roundCorner 10
skinparam defaultFontName Arial
skinparam defaultFontSize 13
skinparam ArrowColor #4e6070
skinparam ArrowFontColor #3d4f5f
skinparam titleFontSize 14
skinparam actorBorderColor #006a62
skinparam actorBackgroundColor #e9f3f4
skinparam usecaseBorderColor #006a62
skinparam usecaseBackgroundColor #e9f3f4
skinparam componentBorderColor #006a62
skinparam componentBackgroundColor #e9f3f4
skinparam interfaceBorderColor #006a62
skinparam interfaceBackgroundColor #ffffff
skinparam nodeBorderColor #4e6070
skinparam nodeBackgroundColor #f4f8fb
skinparam databaseBorderColor #006a62
skinparam databaseBackgroundColor #ffffff
skinparam cloudBorderColor #4e6070
skinparam cloudBackgroundColor #f0f5fa
skinparam artifactBorderColor #006a62
skinparam artifactBackgroundColor #ffffff
skinparam rectangleBorderColor #b0c2d3
skinparam activityBorderColor #006a62
skinparam activityBackgroundColor #e9f3f4
skinparam partitionBorderColor #b0c2d3
skinparam stereotypeCBackgroundColor #ffffff
node "Docker Compose" as H {
node "db" as N0 <<container>>
node "web" as N1 <<container>>
node "api" as N2 <<container>>
}
artifact "FROM node:16-alpine" as IMG0
IMG0 ..> N0 : builds
artifact "FROM node:16-alpine" as IMG1
IMG1 ..> N0 : builds
artifact "FROM nginx" as IMG2
IMG2 ..> N0 : builds
database "Prisma" as DB0
N0 --> DB0
@enduml
Where it runs
Compose services
db web api
Docker base images
7.10. Monitoring
What the code logs, measures and exposes to tell whether it is working.
7.11. Security
Supply chain
Environment variables 1
The page lists names without their values and underlines the ones that look like secrets.
7.12. Testing
- Test files
- 17
- Source files
- 207
- Test cases, about
- 9
- Unit tests
- 17
Code coverage
No measured coverage report in the analyzed sources.
Where the tests are
WordsEnigma/api/src/directives/requireAuth 1 WordsEnigma/api/src/directives/skipAuth 1 WordsEnigma/api/src/services/games 1 WordsEnigma/api/src/services/languages 1 WordsEnigma/api/src/services/letters 1 WordsEnigma/api/src/services/statistics 1
Nothing found for: Public interface, Private interface, Services.
8. Types and file structure
24 declared types, with 12 in the base-relationship overview.
Type diagram
classDiagram
direction TB
class t95c33d5ad155["f"] {
constructor()
}
class tdfd20eddf50b["w6"] {
constructor()
bufferLength()
encoding()
setEncoding()
}
class t2f1e841c76de["e"] {
constructor()
submit()
create()
}
class t4dc7653db721["r"] {
constructor()
create()
}
class t9218f580818e["n"] {
constructor()
}
class t3faaab51d666["s"] {
constructor()
}
class tba189d78e812["IProps"] {
<<interface>>
}
class t1f16c646b417["IState"] {
<<interface>>
}
class t04f5a721d14f["GameBoard"] {
constructor()
eventBus()
componentDidMount()
componentWillUnmount()
}
class tdc6fb562c12d["IProps"] {
<<interface>>
}
class tee5c605d4895["IState"] {
<<interface>>
}
class tb608dc0b97f4["Header"] {
constructor()
render()
}
class b9938495049a9["jwe"] {
<<unresolved_base>>
}
t95c33d5ad155 ..> b9938495049a9 : declared base
class b612c3a755722["p6"] {
<<unresolved_base>>
}
tdfd20eddf50b ..> b612c3a755722 : declared base
class bc2ce90cba9ba["Jqe"] {
<<unresolved_base>>
}
t2f1e841c76de ..> bc2ce90cba9ba : declared base
class b1d2f8b85b03d["zqe"] {
<<unresolved_base>>
}
t4dc7653db721 ..> b1d2f8b85b03d : declared base
class b6e2409b80935["t"] {
<<unresolved_base>>
}
t4dc7653db721 ..> b6e2409b80935 : declared base
t4dc7653db721 <|-- t9218f580818e
class b9589272b3c41["Component"] {
<<unresolved_base>>
}
t04f5a721d14f ..> b9589272b3c41 : declared base
class b5baf1888a7d2["Component"] {
<<unresolved_base>>
}
tb608dc0b97f4 ..> b5baf1888a7d2 : declared base
Unresolved bases remain labelled; full signatures are not reconstructed.
9. Reference
221 / 221 eligible files read (962 in the tree); 0 oversized, 0 failed reads and 2 syntax diagnostics.
What the scan covers
Known dependency/build folders, credential files and binaries are excluded. The scan covers READMEs, recognized manifests and parser-supported source files.
Linguist statistics cover the whole repository and may include other languages.
11. Files to read 3
12. Glossary
Repository
The versioned source files, configuration, and history of a project.
README
The repository’s entry document, usually covering its purpose and initial setup.
Dependency
A library, tool, or service that another component needs to build or run.
API
An interface through which software components exchange requests and results. An API does not have to use HTTP.
Container
An isolated process environment created from an image. Persistent data needs storage outside the container’s disposable filesystem.
Volume and bind mount
A volume is storage managed by the container platform; a bind mount exposes a chosen host path inside a container.
Published port
A host port mapped to a service’s container port. Publishing a port can expose that service beyond its container network.
CLI
A text interface in which commands and arguments select operations. Exit codes let scripts detect success or failure.
Build
The steps that turn source files and dependencies into a runnable program or distributable artifact.
Database
A system for storing and querying structured records. Its schema, access rules, and persistence determine how the application can use that data.
Fork
A separate repository derived from another project. A change in a fork is not automatically a change in the upstream project.
13. References
- antoinebou12. (2026, November 5). WordsEnigma. [Software repository] github.com.
- antoinebou12. (2026, November 5). WordsEnigma: README. [Repository documentation] github.com.
- antoinebou12. (2026, November 5). WordsEnigma/package.json. [Source file] github.com.
- antoinebou12. (2026, November 5). WordsEnigma/api/db/schema.prisma. [Source file] github.com.
- antoinebou12. (2026, November 5). WordsEnigma/api/src/services/games/games.ts. [Source file] github.com.
- Boucher, A. (2026, October 23). WordsEnigma: A word game across Redwood and Prisma. [Project article] antoineboucher.info.
Sources without a publication date show the date they were last checked, November 5, 2026. File links retain the inspected revision where available.