Make Your Own: rosters, draft classes, faces, logos and fields
Do or Dynasty ships with a fictional league. Everything else is a file you make: a roster for any league and any season, a draft class, a pack of faces, team marks or home fields. This guide is the short road. The format references next to it have every field.
You do not need to write JSON by hand. The two prompts below describe the file format exactly as this version of the game validates it. Paste one into any assistant, fill in the blanks, and load what comes back. The same prompts are in the game under New Game → Make Your Own → Copy, which is the copy to use if you are unsure which version of this page matches your build.
What you can make, and where it loads
| File | What it is | Loads at |
|---|---|---|
Roster .json |
The league: teams, players, staff, owners, history | New Game → Roster → Load .json file |
Draft class .json |
One or more future draft classes | New Game → Draft Classes, or Scouting → Draft Class during a career |
Skins .zip |
Faces for players, prospects, coaches and owners | New Game → Faces, Logos and Fields, or Settings → Skins Package |
Logo pack .zip |
A team mark per slot | Same places as skins, from your own disk only |
Field pack .zip |
A home-field image per slot | Same places as skins |
Every load shows a report. Errors block and say exactly what to fix; warnings explain what the game filled in. The validation glossary decodes each one.
The three rules that make any league fit
The game has 32 slots, and the ids are fixed. Any league with up to 32 franchises maps onto them. You rename and recolor a slot in the roster's
teamsblock; you cannot add a 33rd or delete one. The ids:buf mia ne nyj bal cle pit cin hou ind jax ten den kc lv lac dal nyg phi was chi det gb min atl car no tb ari lar sf seaA franchise keeps one id through moves and renames. Use the id of the city the franchise plays in today for every era, and put the era's city, nickname and colors in the
teamsoverride. A 1982 season has 28 franchises: author those 28 onto their modern ids, leave the other four unauthored (the game generates those clubs and the report says so) or name them as fictional expansion teams.Money is optional. The game enforces a modern salary cap in every season. Authored contracts must fit under it; a player with no contract gets a cap-valid one generated. For a historical season, omit contracts entirely. For a current one, give deals to the ten or so players whose contracts define the team and leave the rest.
Building a roster with an assistant
A full league is around 1,900 players. Asking for all of it in one answer is how you get invented players. The reliable method is one team per pass: 32 small answers, then a trivial merge. Each pass is small enough that the assistant gets the details right.
Step 1: the prompt, one team at a time
Copy the block below verbatim, replace the four placeholders, and run it once per team.
Save each answer as <teamid>.json.
| Placeholder | Put |
|---|---|
<LEAGUE> |
The league, in your words: a real league, a historical one, or one you invented |
<SEASON> |
The calendar year the file's first season is played in |
<TEAM> |
The franchise as it was known that season |
<TEAMID> |
The slot id from the list above |
You are building a roster file for the football management game Do or Dynasty. Output ONLY a JSON object, no prose, no markdown fences.
Produce the roster for the <TEAM> (team id "<TEAMID>") of the <LEAGUE> for the <SEASON> season.
Rules:
- Output shape: { "players": [ ... ], "staff": [ ... ], "teams": [ ... ] }. One team per pass; I merge the files myself.
- The game has exactly 32 team slots with these ids: buf mia ne nyj bal cle pit cin hou ind jax ten den kc lv lac dal nyg phi was chi det gb min atl car no tb ari lar sf sea
A franchise keeps ONE id through relocations and renames (use the id of the city it plays in today). "teams" holds a single override for this slot: { "id": "<TEAMID>", "city", "nickname", "abbreviation", "primaryColor", "secondaryColor" } with the names and colors this franchise used in <SEASON>. Never invent an id.
- Each player: { "name", "team": "<TEAMID>", "position", "ovr", and optionally "age", "jersey", "pot", "college", "draft", "contract", "careerStats", "awards" }.
- "position" is one of: QB RB FB WR TE OT OG C EDGE DT MLB OLB CB FS SS K P
Map real positions: edge rusher/DE -> EDGE, defensive tackle/NT -> DT, off-ball linebacker -> MLB or OLB, strong safety -> SS, free safety -> FS, guard -> OG, center -> C, tackle -> OT, every corner -> CB.
- "ovr" is 0-100 (stars ~88-99, starters ~78-87, depth ~62-77). Rate from how the player actually played that season; do not copy ratings from any other game or product.
- "draft": { "year", "round", "pick" } when known.
- "contract" (millions): { "years", "totalM", "guaranteedM", "yearSigned", "throughSeason" }.
The game enforces a $280M hard cap for every season, so keep this team's total average annual value under $252M. Give deals ONLY to the ~10 best players and leave the rest with no contract; the game generates cap-valid deals for everyone without one. For a historical season, omit "contract" on everyone.
If the deal was signed BEFORE <SEASON>, you MUST include "throughSeason": the calendar year of the deal's FINAL season. An extension's advertised length counts only new money, which starts the year AFTER signing, so "years" + "yearSigned" alone places an extension 1-3 seasons early. Keep both truthful and add "throughSeason". You may omit it only for a rookie deal or a signing made in <SEASON> itself.
- "careerStats" (OPTIONAL, for stars and starters): one object per PAST season, each with "season" (a calendar year strictly before <SEASON>), "team" (the id he played for that year), "gamesPlayed", and only the fields that fit his position, using these exact names:
QB: passingYards passingTDs interceptions completionPct passAttempts passCompletions
run: rushingYards rushingTDs
rec: receivingYards receivingTDs receptions
def: tackles sacks forcedFumbles interceptionsDef passDeflections
K: fgMade fgAttempted fgPct
P: punts puntYards puntsAvg
Per-season lines only, never career totals. Omit careerStats for depth players.
- "awards" (OPTIONAL): one object per honor per season, { "season", "award", "team"? }, where "award" is one of: MVP OPOY DPOY OROY DROY ALL_LEAGUE ALL_STAR TOP_100 CHAMPION
(ALL_LEAGUE = first-team all-league, ALL_STAR = the all-star game, CHAMPION = won the title that season.) "season" is the year the honor was won FOR and is strictly before <SEASON>. List ONLY honors you are certain of: these count toward the Hall of Fame.
- "staff": the head coach, coordinators and general manager as { "name", "team": "<TEAMID>", "role" } with "role" one of: GM AGM HC OC DC STC QBC RBC WRC OLC DLC LBC DBC SCT TRN
Add "careerRecord" for the head coach when you know it: one { "season", "team", "role", "wins", "losses", "playoffResult" } per season coached.
- Include 45-53 players across all position groups (at least 2 QB, 2 RB, 5 WR, 2 TE, 6 OL across OT/OG/C, 6 DL across EDGE/DT, 4 LB across MLB/OLB, 5 DB across CB/FS/SS, 1 K, 1 P). The game fills any gaps.
- State facts a fan knows. Do not invent attribute vectors, and omit any field you are not sure of rather than guessing.
Return the JSON now.
Step 2: merge the files
Put all the per-team files in one folder and run this. It concatenates every file's arrays
and adds the required top-level fields. Save it as merge.mjs, then run
node merge.mjs ./teams-folder my-league.json.
// merge.mjs: concatenate per-team roster files into one importable file.
import { readdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
const [, , dir = ".", out = "my-league.json"] = process.argv;
const merged = {
formatVersion: 1,
meta: { title: "My League", author: "Me", season: 2026 },
teams: [], players: [], freeAgents: [], staff: [], history: [],
};
for (const file of readdirSync(dir).filter((f) => f.endsWith(".json") && f !== out)) {
const part = JSON.parse(readFileSync(join(dir, file), "utf8"));
for (const key of ["teams", "players", "freeAgents", "staff", "history"]) {
if (Array.isArray(part[key])) merged[key].push(...part[key]);
}
}
writeFileSync(out, JSON.stringify(merged, null, 2));
console.log(`Wrote ${out}: ${merged.players.length} players, ${merged.staff.length} staff, ${merged.teams.length} team overrides.`);
Set meta.season to the same year you used for <SEASON>, and meta.title and
meta.author to what you want shown on the load screen.
Step 3: load it and iterate against the report
New Game → Roster → Load .json file. The report lists every problem at once. Paste the error lines back to the assistant with "fix these", re-merge, reload. When it is clean, start your career. The exact bytes of a finished file reproduce the exact league for anyone you share it with.
Things worth adding once the basics load, all described in the roster format reference: league championship history, a legendary coach's accomplishments and career record, hall-of-fame players, coaching trees, traded draft picks, conference labels and per-player tendencies.
Building a draft class with an assistant
Same idea, one position group per pass. Run the prompt once each for QB, RB, WR, TE,
OL (OT/OG/C), EDGE, DT, LB (MLB/OLB), CB and S (FS/SS), concatenate the arrays into one
prospects array, and wrap it:
{
"formatVersion": 1,
"draftClasses": [
{ "year": 2027, "prospects": [ /* the concatenated arrays */ ] }
]
}
The first draft a new career runs is the year after meta.season, so a 2026 roster's
first custom class is "year": 2027. Only the notable names are needed; the game fills
the rest of the class. Prospects start fully unscouted whatever the file says, so a file
cannot hand you a pre-scouted board.
You are building a draft-class file for the football management game Do or Dynasty. Output ONLY a JSON array, no prose, no markdown fences.
Produce the notable <POSITION GROUP> prospects of the <LEAGUE> <DRAFT YEAR> draft class.
Rules:
- Output shape: a JSON array of prospect objects. One position group per pass; I concatenate the arrays myself.
- Each prospect: { "name", "position", "ovr", "pot", and optionally "age", "jersey", "college", "collegeSize", "projectedRound", "storyline" }. No "team", no "contract", no "draft": a prospect predates all three.
- "position" is one of: QB RB FB WR TE OT OG C EDGE DT MLB OLB CB FS SS K P
Map real positions: edge rusher/DE -> EDGE, defensive tackle/NT -> DT, off-ball linebacker -> MLB or OLB, strong safety -> SS, free safety -> FS, guard -> OG, center -> C, tackle -> OT, every corner -> CB.
- "ovr" is the prospect's ability NOW, as a rookie, and "pot" is his ceiling; "pot" must be >= "ovr". Use these bands:
generational top-5 talent: ovr 74-79, pot 92-97
first round: ovr 70-76, pot 85-92
day two: ovr 66-72, pot 78-86
day three: ovr 60-68, pot 70-80
Rate from the prospect's own college play and scouting consensus; do not copy ratings from any other game or product.
- "age" is draft-day age (20-24). "collegeSize" is "Large", "Medium" or "Small". "projectedRound" is 1-7 and only helps me organize; the game hides it.
- "storyline" (OPTIONAL, for the notable ones): { "blurb": one sentence of backstory, "headline": a short ticker line, "tags": [free-form strings], "weight": 1-5 }.
- Only the notable names are needed; the game fills the rest of the class with generated prospects. Omit any field you are not sure of rather than guessing.
Return the JSON array now.
Faces, logos and fields
A skins pack is a zip with a manifest.json and WebP images. The
skins format reference has the manifest, the matching rules, and the
image sizes. Three things to know before you start:
- Names must match the roster file exactly. The manifest names people the way the
roster does, with
teamandposition(orrole) so matching never guesses. The load report lists every entry it could not match. - Coverage can be partial. Anyone without a face keeps the game's drawn one. A pack that covers a hundred coaches and owners and nobody else is a good pack.
- A pack you share is a publication. Every image in it has to be one you may publish: your own art, public-domain images, or Commons images with a permissive license and an attribution table. Not headshots from a sports site, not team press photos, not real team marks. The skins reference's Sources and rights section says exactly where the line is. A pack you load only on your own machine is your own business.
Logo packs load from your own disk only. The game's online catalog does not list or install them, by design.
Sharing what you made
Post the file wherever your community lives. A roster or draft class is facts about a sport and is yours to share. If you want a roster or draft class listed in the game's online catalog so other players can download it in one click, the catalog's own guide says how a package is submitted and what it must carry. Faces, logos and fields are never listed; they travel as files.
Reference
- Roster format: every field, every tier, the contract rules.
- Draft-class format: prospects, rating bands, storylines.
- Skins format: manifest, matching, logos, fields, sources and rights.
- Validation glossary: what every error and warning means.
- Examples, small runnable files: the minimal roster, an editor-grade roster, a legendary coach, hall-of-fame legends and a draft class.