Design 002 · Standard
Green and white
This is the FedM8 app. Warm paper, olive buttons, dark green words, serif headings and plain sans-serif controls. Chat comes first: members land in it, and every section carries a room. Build every new screen, tool or page from this page.
- Use for
- The app: Chat, Veterans, Contracts, Grants, Get Certified, Learn. Every new screen, tool or page.
- Fonts
- Newsreader (then Source Serif 4) for headings, DM Sans for everything else
- Palette
- Canvas
#f5f3ec, paper#fffef9, olive#526547, ink#29372e - Reference sizes
- Desktop 1440 × 1000 · phone 375 × 812 · light only
- Source
DESIGN.md,assets/approved-design.css,assets/fedm8-room.css,assets/chat-words.js- Status
- Standard · version 2026-10-21
How to use this page
- Check that this is the right design. The app and every new screen use 002. Brand marks, walkthrough videos, YouTube thumbnails, social posts and print use 001 Navy and gold.
- AI agents: read
/design/002/tokens.jsonfirst. It holds every color, size, space, corner, word and rule on this page in a form a program can read. - Find the part you need, read its Do and Don't, then copy its snippet. Change the words; keep the classes and the order.
- Before you ship, check the screen against Accessibility and the checklist in For AI agents.
- If this page and
DESIGN.mddisagree,DESIGN.mdwins until the page is fixed. Say so in Comments.
Every sample on this page is fictional and carries a Sample label. The samples are drawn with page-only classes (they start with x2-) that copy the app's values. In the app, use the app classes and components named in each snippet.
Principles
Six rules carry the whole look. When a case is not covered here, pick what keeps the screen calm, honest and plain.
Calm
Warm paper, thin lines and one olive accent. Nothing blinks, slides in or shouts. Color marks a state, never decoration.
Light only
The design stays light even when a device asks for dark mode: dark green ink on paper, always.
One main action per view
One olive button per view, such as Post or Save and continue. Everything else is a ghost button or a link.
Honest states
Say what is true: loading, nothing yet, could not load, saved. No invented people, counts or scores. Leave a number out rather than guess it.
Plain words
Short sentences a busy owner reads once. Name the thing, then the next step. Define a term where it appears.
44px targets
Anything a finger presses is at least 44 by 44 pixels on a phone, with a visible 2px olive focus ring for the keyboard.
Do
- Let the content lead. The frame stays quiet.
- Keep the rules line, where a post goes and the acknowledgment in sight wherever they affect an action.
- Put longer guidance in the help dialog behind the round ? button.
- Show the real count, or no count.
Don't
- Hero banners, gradients or glows. The one framed topic photo is placed by the app; never add your own.
- A "live" dot on anything that does not update itself.
- Sales words: unlock, supercharge, don't miss out.
- A dark theme, or a second accent color.
Colors
Nine core tokens make every screen. The named extras come from the app's own files; use each one only for the job on its card. Press a hex value to copy it. The Tweak button changes the core tokens on this page, in your browser only.
Core tokens
--fd-bgThe page behind everything.--fd-paperCards, panels, the header, the dock, dialogs.--fd-softQuiet fills: chips, the selected room tab, hover in rooms.--fd-inkBody text and headings.--fd-mutedSecond lines, meta, hints, rail links at rest.--fd-lineCard and panel edges, dividers. Too light for a field edge.--fd-greenThe one main button, the current rail bar, the focus ring.--fd-green-darkText on light fills: ghost buttons, the current rail item, room links.--fd-mintCount pills and the match percent.Named extras
--fd-line-2Ghost button and dialog edges, the Sample frame.--fd-field-lineInputs, selects and text boxes. Passes 3:1 on paper.--fd-hoverA rail link under the pointer.--fd-hover-2A ghost button or header button under the pointer.--fd-activeThe current rail item and room, a pressed choice, the P tile.--fd-selected-lineA selected card's border, the plan tile edge.--fd-calloutCallouts and the Match-M8 box.--fd-olive-hoverThe main button under the pointer.--fd-linkUnderlined links in running text.--fd-labelSmall uppercase group labels in the rail and My rooms.--fd-chip-inkText on fact chips.--fd-count-inkNumbers on mint and the match percent.Status and Chat
--fd-ai-bgThe pinned FedM8 AI note in a room.--fd-ai-markThe AI avatar and the Pinned pill.--fd-amberThe heads-up under a box, "Waiting on an answer".--fd-due-bgThe due date chip.--fd-fail-bgThe one line that says a read failed.--fd-red-softA post the server refused.--fd-redRemove mine, field errors.--fd-onlineThe online dot. Only where a real heartbeat backs it.--fd-answeredAnswered, This answered it, Saved.--fd-selectionSelected text and the tap highlight.Contrast
Every text pair passes WCAG 2.2 AA (4.5:1). Edges a person must see, such as a field or the focus ring, pass 3:1. The light lines are decoration only.
| Pair | Looks like | Ratio | Use |
|---|---|---|---|
| Ink on paper | Aa | 12.38:1 | Body text, titles |
| Ink on canvas | Aa | 11.26:1 | Page titles on the canvas |
| Muted on paper | Aa | 6.04:1 | Second lines, meta |
| Muted on canvas | Aa | 5.50:1 | Rail links at rest |
| Muted on soft | Aa | 5.34:1 | Text in soft fills |
| Paper on olive | Post | 6.28:1 | The main button |
| Paper on olive hover | Post | 8.45:1 | The main button under the pointer |
| Dark olive on current | Aa | 7.79:1 | Current rail item, P tile |
| Link on paper | Aa | 7.19:1 | Links in running text |
| Label on canvas | AA | 5.21:1 | Uppercase group labels |
| Chip ink on soft | Aa | 7.26:1 | Fact chips |
| Count ink on mint | 12 | 6.86:1 | Count pills |
| Due ink on due | Aa | 5.90:1 | Due date chip |
| Amber ink on heads-up | Aa | 8.03:1 | Heads-up, Waiting on an answer |
| Fail ink on could not load | Aa | 9.33:1 | The could-not-load line |
| Danger text on paper | Aa | 8.10:1 | Remove mine, errors |
| Placeholder on white | Aa | 4.83:1 | Hint text inside a box |
| Focus ring on paper | Aa | 6.28:1 | Keyboard focus (3:1 needed) |
| Field edge on paper | Aa | 3.16:1 | Inputs, selects, text boxes (3:1 needed) |
| Line on paper | Aa | 1.36:1 | Decoration only: card edges, dividers |
| Strong line on paper | Aa | 1.52:1 | Decoration only: ghost button edges |
A ghost button's text carries its meaning, so its light edge is fine. A field's edge is the only thing that shows where to type, so fields use the field edge #81976b.
Typography
Two kinds of letters do the work. A serif gives page, card and dialog titles a calm, bookish feel. DM Sans carries everything a person reads fast or presses. Rooms set their titles in Source Serif 4.
| Family | Weights | Use | App variable |
|---|---|---|---|
| Newsreader | 500, 600 | Page, panel and dialog titles, Chat home headings, serif card titles. Falls back to Source Serif 4, then Georgia. | --font-serif |
| Source Serif 4 | 600, 700 | Room titles, "People to say hi to", the phone room header. Second choice for every serif heading. | none (written in the room files) |
| DM Sans | 400, 500, 600, 700 | Body, buttons, labels, chips, meta and numbers. | --font-sans |
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,[email protected],400;9..40,500;9..40,600;9..40,700&family=Newsreader:opsz,[email protected],500;6..72,600&family=Source+Serif+4:opsz,[email protected],600;8..60,700&display=swap">This is the link os.html uses, without Cormorant Garamond: that family belongs to the 001 wordmark, and nothing in this design uses it.
Type scale
Do
- One page title per screen, in the serif.
- Sentence case everywhere: "Ask your people", not "Ask Your People".
- Keep numbers in DM Sans so they line up.
Don't
- Serif for buttons, labels, chips or body text.
- Uppercase anything except the small group labels.
- Text below 10px, or bold for a whole paragraph.
Space and shape
Spacing moves in small steps. Corners stay small: 5px on controls, 6px in rooms, 8px on cards, 10px on dialogs, and full round only on pills. Shadows are barely there; the thin line does the work.
Spacing steps
4pxInside a chip: icon to word.6pxA plan tile after its tool's name; chips in a row.8pxBetween buttons; small stacks.10pxBetween cards in a list and posts in a room.12pxInside a post; the composer.14pxInside a result card.16pxBetween page head and tabs; the Match-M8 box.20pxPanel sides; Chat home columns.22pxBetween section tabs.24pxTop of the content; dialog padding.28pxHeader sides; left of the rail; right of the content.30pxRail to content.44pxThe smallest target a finger presses.Corners
Shadows
0 1px 3px #29372e040 8px 25px #29372e160 8px 24px #29372e2e0 18px 80px #1f2f25400 -2px 12px #29372e060 2px 6px #29372e33Layout
Two reference sizes: desktop 1440 × 1000 and phone 375 × 812. Desktop has a 64px header, a 190px section rail and content that starts about 248px from the left. The phone swaps the rail for a six-item dock at the bottom and keeps one column.
Desktop: 1440 × 1000
| Part | Size | Notes |
|---|---|---|
| Header | 64px tall · 28px sides · paper · 1px line below | Logo 40px and the FedM8 wordmark on the left; Inbox and My Profile as 44px icon buttons on the right. |
| Section rail | 190px wide · 28px from the left | Groups Community, Opportunities and Readiness; Your workspace below a line. |
| Gap | 30px | Between the rail and the content. |
| Content | from about 248px · 24px top · 28px right · 1454px widest | Page head, then tabs, then the work. |
| Page head | 31px serif title + 44px round ? button | The ? opens the help dialog. No paragraph under the title unless it changes an action. |
| Public scope tabs | 48px strip · 44px buttons | Discussions, NAICS rooms, Find teammates, Live All (Read only). |
| Section tabs | 44px tall · 22px apart · 2px olive underline on the current one | More tools holds the specialist tools. |
| Topic photo | 6px paper frame · 1px line · 8px corners · image 170px to 230px tall with 4px corners, cropped to fill. On Chat home: 5px frame, 118px image. On a phone: 5px frame, 96px image. | Placed by approved-design.js with its own alt text. Never add one yourself. |
Desktop, real pixels
On a small screen, scroll the sample sideways to see all of it.
Phone: 375 × 812
Do
- The rail on desktop, the dock on the phone. Never both.
- One column on the phone, with no sideways scrolling.
- Short scope labels on the phone: Discussions, NAICS, People, Live All.
- Leave room under the last post so a pinned box never covers it.
Don't
- A floating chat button over the dock.
- A hero band or a photo header of your own. The app places one small framed topic photo where it fits.
- A second rail, or a menu order other than Chat, Veterans, Contracts, Grants, Get Certified, Learn.
Buttons and fields
Every control is at least 44px tall, with 5px corners and DM Sans 500 at 12px. One olive main button per view; everything else is a ghost button or a link. Every field has a label above it and the olive field edge.
Buttons
| Kind | Looks | Use it for | App class |
|---|---|---|---|
| Main | Paper on olive #526547; hover #3e5234 | The one action that moves the work: Post, Save and continue, Search. | btn |
| Ghost | Dark olive on paper, 1px #cbd4bf edge; hover #edf1e5, edge #aebf9c | Every other action: Cancel, Save this search, See all past awards. | btn ghost |
| Danger | #9a302d on #fff5f1, edge #d9b2a9 | Only the last step of something that cannot be undone. | btn danger |
| Busy | The same button at 55% to 60% | Only while a request is in flight. To stop an early press, keep the button live and say what is missing. | disabled |
| Text link | #435e36, 500, underlined | Going somewhere: See plans, Check what you do. | a |
Fields
Your posts show this name when you post as your company.
A NAICS code is 6 digits. Fix it or leave it empty.
| Part | Value |
|---|---|
| Field | 44px tall · 8px 10px padding · 5px corners · 1px #81976b edge · paper · DM Sans 13px. Inside #main the app gives every field this edge. |
| Text box | The same, 88px or more, grows with the words. Room boxes are white, 6px corners, 15px text. |
| Label | Above the field · DM Sans 600 · 12px · ink |
| Hint | Under the field · 12px · muted · linked with aria-describedby |
| Error | Under the field · 12.5px · #8f2d22; the field gets a 2px ink edge and aria-invalid="true" |
| Placeholder | #6a7565. An example, never the label. |
| Checkbox | 20px (18px in rooms) · olive accent · the words are the label, so the whole line is the target |
| Phone | Field text is 16px so the phone does not zoom in. |
Focus ring
App-wide: a 3px olive outline #526547, 3px outside the control; fields keep it 1px outside. Inside rooms, chips and plan tiles it is 2px, 2px outside. It passes 3:1 on paper and canvas. Press Tab on this page to see the real ring on any sample control.
<button type="button" class="btn">Save and continue</button>
<button type="button" class="btn ghost">Save this search</button>
<button type="button" class="btn danger">Remove</button>
<label for="company">Company name</label>
<input id="company" type="text" aria-describedby="company-hint">
<p id="company-hint" class="muted">Your posts show this name when you post as your company.</p>
<label><input type="checkbox"> I'm not working on this buy for the government, and I won't share nonpublic information.</label>Do
- Put the main button last in its row.
- Name buttons with a verb and the thing: Save this search, Post reply.
- Say what a field needs before someone types, and what went wrong after, right under the field.
- Give icon-only buttons an
aria-label.
Don't
- Two olive buttons side by side.
- A placeholder as the only label.
- Red for anything except errors and removing.
- Remove the focus outline without a stronger one in its place.
Chips and counts
A chip states one fact. Most chips are quiet: soft fill, thin line, 11px words. Color is saved for meaning: the Talk door, a count, a due date, an answer and a host.
| Chip | Value | Rule |
|---|---|---|
| Fact | 3px 7px · 4px corners · #eef1e7 · #42533a · 11px | Set-aside, code, place, notice type. Plain words, no color. |
| Due date | #825322 on #fff2d8, edge #eddbb6 | Only the response deadline. |
| Room kind | 22px · round · soft · dark olive 600 · 11.5px; grant #e9f4ea; code #f6efdc | Contract, Grant, Award, Lesson, Code 541519, Room, Certification. First thing in a room's head. |
| Talk · N | 34px · round · 1px olive edge · dark olive 600 · 13px · speech-bubble icon | The door into a room, wherever a contract, grant or code appears. The number is posts. No number when the count did not load. |
| Count | #31553b on mint #d9eddd, edge #c5ddc9, 600 | A real count only. |
| Answered | #2f6b3a on #e6f1e3, edge #b9d4b3 | The thread's asker marked a reply. Never set by FedM8. |
| Waiting | #5c4708 on #fbf3dc | A question with no answer for over a day. |
| Founding crew, Staff, Greeter | Olive edge on #eef2e6 | Set by the server, never typed by the poster. |
| SAM lists SDVOSB | #22502a on #e3f0e3 | Only from SAM data for a verified UEI. Never from a profile. |
| FedM8 AI | Paper on dark olive, 4px corners, 700 | The room host. Always with "not a member". |
// A "Talk · N" door for a list row. Counts fill in from one batched read.
var door = FedM8TalkDoors.chip(document, {
item: FedM8TalkDoors.itemFor("notice", noticeId), // "grant" -> "grant:<id>", "naics" -> "naics:<code>"
signedIn: !!ctx.user,
title: notice.title
});
row.appendChild(door);
FedM8TalkDoors.counts([door.getAttribute("data-td-item")], { client: ctx.sb, user: ctx.user && ctx.user.id })
.then(function (map) { FedM8TalkDoors.fill(list, map); });Do
- One fact per chip, in plain words.
- Keep chips in one row that wraps.
- Let the door's
aria-labelname the room and the count: "Talk about …, 12 posts".
Don't
- Make a chip a button unless it opens something.
- Invent a status color, or turn a fact chip green to look good.
- Show a "SAM lists" chip from anything but SAM data.
Cards and panels
Paper on canvas, a 1px line, 8px corners and almost no shadow. A panel holds a tool or a form. A card holds one thing in a list. A selected card gets a darker edge and a 2px olive bar inside its left edge, never a fill.
What the buyer wants
Help desk support for about 400 people, Monday to Friday, 7 a.m. to 6 p.m. Tier 1 and Tier 2 calls. A site visit on Nov 3.
Metrics, callouts and dialogs
Open pursuits
3
1 due this week
Saved searches
2
5 new notices since Monday
Rooms you follow
4
2 with new posts
The short version
The buyer wants one firm to run the help desk for about 400 people. Small businesses with an SDVOSB certification can bid.Contracts help
Search by keyword or NAICS. Open a notice to read its brief, requirements and files. Public discussion stays with that notice. Keep bid files, pricing and proposal work in your private pursuit.
| Part | Value | App class |
|---|---|---|
| Panel | 18px 20px padding · 14px below · heading DM Sans 600 15px · text 13px muted | panel inside #page-content |
| Card | 14px padding · 10px apart · title DM Sans 500 16px · meta 12px muted | card |
| Selected card | Edge #b8c5aa · box-shadow: inset 2px 0 #81976b | sel on the card |
| Metric | Label 10px 600 +0.7px uppercase muted · number DM Sans 500 25px · two across on the phone | metrics > metric > lbl + val |
| Callout | 12px · 6px corners · #f0f4e8 · edge #cfd8c2 | page-specific |
| Lede | #eef1e7 · 2px #81976b bar on the left · 11px 13px | page-specific |
| Dialog | Paper · 10px corners · 1px #cbd4bf · 24px padding · up to 520px · shadow 0 18px 80px #1f2f2540 · scrim #23302366 · 44px close button | native <dialog>; the help dialog is drawn for you |
<section class="panel">
<h2>What the buyer wants</h2>
<p>Help desk support for about 400 people, Monday to Friday.</p>
<button type="button" class="btn ghost">Open the files</button>
</section>
<div class="metrics">
<div class="metric"><div class="lbl">Open pursuits</div><div class="val">3</div></div>
</div>Do
- One idea per panel, with a plain heading.
- Show selection with the edge and the inside bar.
- Close a dialog with ×, Escape and Cancel, and return focus to what opened it.
Don't
- Cards inside cards inside cards.
- Heavy shadows, colored card tops or gradients (Win Kit's olive top line is the one exception).
- A dialog for something a line of text can say.
Chat
Chat comes first. Members land on Chat home, and every contract, grant and NAICS code has its own room. One component draws every room, so each one has the same head, tabs, actions, ⋯ menu and box. The rules line, where a post goes and the box stay in sight while someone writes.
- Public name
- Contract Chat
- In the app
- Chat, at
/os.html#/talk - A conversation
- A room. Rooms hold posts; posts hold replies.
- The action
- Post. In a reply box: Post reply.
- Room host
- FedM8 AI · not a member
- Drawn by
assets/chat-home.jsandassets/fedm8-room.js; every word inassets/chat-words.js
Chat home on a desktop
Three columns: My rooms, then Ask your people above the new posts, then one card at a time. The sample is the whole 1440 × 1000 screen, scaled down to fit.
Chat
Ask your people
Public · Keep prices, bids and nonpublic information out.
This will post in: your NAICS 541519 room ·
2 new posts left today · replies are open
New in your rooms
Unanswered near you
“Has anyone cleaned the Example Lake visitor center? Do they want day porters or only a night crew?”
Waiting over a day. Can you answer it?
Has anyone done a site visit at Fort Example? Wondering how far the help desk is from the gate.
We're a prime on a help desk recompete and need a sub with Tier 2 network support near Fort Example. Roles only here; we can talk more in a private chat.
Hi all. I run a two-person IT shop and I'm learning how set-asides work. Glad to be here.
Topic photo
placed by the app
Best contract for you
Sample · Help desk support, Fort Example
12 posts about it
Basic shows all your matches, with fit and summaries. See plans
On a small screen, scroll the sample sideways to see all of it.
| Part | Value | Words |
|---|---|---|
| Grid | My rooms 190px to 220px · middle takes the rest · rail 240px to 290px · 16px between rows, 20px between columns · 1180px widest. My rooms and the rail stay in place 82px from the top while the middle scrolls. | none |
| My rooms | Paper card · rows 38px, DM Sans 13px · current row #e4ead8 with a 3px olive bar inside its left edge · group titles 11.5px muted · "N new" pill #e6ecdd | My rooms · Rooms · Your codes · My conversations · Messages · More rooms · New means posted in the last 24 hours. |
| Ask your people | Paper card, 16px 18px · Newsreader 600 21px · rules line 12px above a white box (#b9c4ab edge, 6px corners, 72px tall) · destination 13px · Post 40px, olive | Public · Keep prices, bids and nonpublic information out. · This will post in: your NAICS 541519 room · Change · 2 new posts left today · replies are open · Post |
| New in your rooms | Cards 13px 15px, 8px corners, 10px apart · 34px initials · name 600 13.5px · meta 12px · words 14px, five lines at most · foot 12.5px | in General · 2h · 2 replies · Helpful · M8 4 · ⋯ · Open |
| Unanswered near you | #f7f0dc, edge #e3d6ae, title 600 14px #5a4a17 | The question in quotes · NAICS 561720 · 1d · no replies yet · Waiting over a day. Can you answer it? · Answer |
| Right rail | The topic photo (118px), then one card at a time · kicker #6b5a1f · Newsreader 600 17px title · chips 11.5px round | Best contract for you · Who's around · Wins and milestones · Say hello · Help a newcomer · 1 of 3 · Next: Who's around |
| 761px to 1180px | Two columns. The rail moves under the stream and scrolls with the page. | none |
| Phone, 760px and under | One column: Ask, Say hello (new members), My rooms as one sideways row of 44px pills, the stream, the rail. No topic photo. | Group titles drop out; the rooms keep their names. |
// Chat home is drawn for you on #/talk. assets/commons-feed.js calls it:
FedM8ChatHome.render(root, ctx, isCurrent); // ctx: { sb, user, account, plan }
// Every word comes from one file. Read it; never retype it.
var W = FedM8ChatWords;
W.chatHome.askTitle; // "Ask your people"
W.chatHome.streamTitle; // "New in your rooms"
W.rulesShort; // "Public · Keep prices, bids and nonpublic information out."
W.helpfulLabel(4); // "Helpful · M8 4" (just "Helpful" at 0)A room
Every contract, grant, award, NAICS code and topic gets this same room. Here is a contract room as a member sees it, with the ⋯ menu drawn open on Lena K.'s reply.
Sample · Help desk support, Fort Example
Example Command · Fort Example · Due Nov 14
The buyer wants one firm to run a help desk for about 400 people, Monday to Friday, 7 a.m. to 6 p.m. It is set aside for SDVOSB firms. Questions are due Nov 4 and offers Nov 14.
FedM8 AIWaiting on an answer · pinned · not a member
1 question in this room is still waiting on an answer. If you know, reply.
Has anyone done a site visit at Fort Example? Wondering how far the help desk is from the gate, and how long badges take.
2 replies
I walked it last year. The help desk is in Building 12, about ten minutes from the main gate. Ask the contracting officer in writing what the visit covers.
✓ This answered it · marked by Dana R.
1 reply
Thanks, that helps.
Badges took me about a week there. Start the form early.
Needs a sub
Anyone here with Tier 2 network support near Fort Example? We're a prime on this one and want a sub for the network side.
Talk about the work and who you need. Keep prices, bids and contact details out of open rooms. Share prices only privately with teammates, under a signed teaming agreement. Ask the contracting officer about the requirement, in writing.
2 new posts left today · replies are open
Roles only. Keep prices, rates and whether you'll bid out of the room.
Room parts
Your own post, ⋯ open
We can cover Tier 1 nights if a prime needs it. Happy to talk roles in a private chat.
You follow this thread because you posted it. We'll tell you when someone answers.
A reply box
18 replies left today
A NAICS code room's Monday note
FedM8 AIMonday note · pinned · not a member
Last 7 days in 541519: 6 new notices, 2 due in 10 days and 1 grant that matched by words.
- Sample · Help desk support, Fort Example · Example Command · SDVOSB
- Sample · Network refresh, Example Air Base · Example Wing · Small business
- Sample · Rural IT skills grant · Closes Dec 9
Sources: SAM.gov, Grants.gov. Built Mon 9:00 AM ET.
Catch up, on a long thread
Catch up. Members say the help desk sits in Building 12, about ten minutes from the main gate, and that badges take about a week.
Held while FedM8 looks
Hidden while FedM8 reviews it. Only you can see it.
Does anyone know who holds the current help desk contract?
Live All, read only
Live All is read-only. To post, pick This one or the code room.
| Part | Value | Words |
|---|---|---|
| Head | Kind chip (22px, round, soft) · title Source Serif 4 600 19px · second line 12.5px muted · Follow (36px, round, olive edge) and its hint on the right | Contract, Grant, Award, Lesson, Code 541519, Room, Member, Certification · Follow · Following |
| Scope tabs | 36px (44px on a phone) · 6px corners · 13px muted; the chosen one gets the soft fill, a line edge and dark olive 600. In the app: role="tablist", arrow keys, Home and End. | This contract · NAICS 541519 · Live All. A grant: This grant · NAICS 541519 (guessed). A code room: This code. |
| New replies pill | Olive, round, 34px, 600 13px, shadow 0 2px 6px #29372e33, centered and held 76px from the top. Checks every 30 seconds while the tab is visible. It never moves the page. | 3 new replies · Show · 1 new post · Show |
| Pinned note | #fbf7e9, edge #eadfb8 · AI initials on #efe2b5 | FedM8 AI · Pinned · AI brief. A code room: Weekly note · From public contract counts. |
| Host card | Paper · 3px olive left edge · 6px corners · chip paper on dark olive, 4px corners, 700 · lead line 15.5px 650 · links 13.5px with 1px lines between | Monday note, Waiting on an answer, Office hours, Friday prompt, New today · "pinned · not a member" · Sources: … Built Mon 9:00 AM ET. |
| Post | 12px padding · 1px line · 6px corners · 10px apart · 30px initials · name 600 13px dark olive · meta and time 11.5px muted · words 13.5px. Your own post #fbfcf6; held posts dashed. | just now · 12m · 2h · Oct 19 · You · Hidden while FedM8 reviews it. Only you can see it. |
| Actions | 32px (44px on a phone) · 6px corners · 12.5px dark olive · Helpful marked: #e8eedf, edge #c9d4bb, 600. Your own post shows its count as plain words, no button. | Helpful · M8 4 · Reply · Follow · Check the record · I'm interested · 2 · ⋯ |
| ⋯ menu | 220px · paper · 8px corners · shadow 0 8px 24px #29372e2e · 40px rows. A bottom sheet on a phone. In the app: role="menu", arrow keys, Escape; Tab closes it. | Someone else's post: Report · Hide this person · People you hid. Your post: Remove mine (your post). |
| Replies | details with a 2px line on the left, 12px in · up to 8 levels; Reply leaves at the 8th · stays open or closed in this tab | 2 replies · 1 reply |
| Answered | Reply edge #a9c9a2 on #f2f8ef · line #2f6b3a 600, under the words | ✓ Answered · This answered it · marked by Dana R. · You marked this as the answer. |
| Box | Rules line 12.5px above the box · white box, 15px words, #c9d1bd edge, 6px corners, 72px · cap 12px · Post 36px olive (44px on a phone) · destination 12px on the left of Post | Add to the conversation · Ask about this contract, or find a teammate. · Public · this conversation · Post · Reply to Dana R. · Write a reply… · Public reply · Post reply · Cancel |
| Looking for | Round chips 32px (44px on a phone); chosen: olive edge, #e5ecdb, 600 | Need a sub · Can sub · Need a prime · Independent specialist. A grant: Lead applicant · Partner · Independent specialist. |
// One call draws a whole room: head, tabs, posts, replies, ⋯ menus, the box.
var room = FedM8Room.mount(host, {
ctx: ctx, // { sb, user, account, plan }
item: noticeId, // "grant:<id>" for a grant, "naics:541519" for a code room
kind: "notice", // "grant", "code", "award", "cert", "room"
code: "541519", // the NAICS tab
label: notice.title,
header: true, title: notice.title, sub: "Example Command · Fort Example · Due Nov 14",
stickyCompose: true, // on a phone the box is pinned above the dock
empty: FedM8ChatWords.empty
});
room.ready.then(function () { /* posts are drawn */ });
// The same actions and ⋯ menu on a post shown outside a room (Chat home does this):
var acts = FedM8Room.actions(post, { ctx: ctx, kind: "post", helpful: true });
// Follow in a header row, with its hint:
head.appendChild(FedM8Follow.button(ctx, noticeId, { hint: true, what: "conversation" }));Do
- Mount every conversation with
FedM8Room.mount, and link to it with a Talk door. - Keep the rules line above every box and where the post goes next to Post.
- Ask for the acknowledgment before a first post in a contract or grant room.
- Keep unsent words in the box after any failure, and say "Not sent yet (kept in this tab)".
- Let the asker mark the answer. Show "✓ Answered" on the thread.
Don't
- Build a second chat, chat bubbles or a floating chat button.
- Typing dots, read receipts or a "live" dot in a room.
- Move the page when new posts arrive. Show the pill.
- Give FedM8 AI a Helpful button, a profile or a member's voice. It is always "not a member".
- Hide Report or Hide this person behind a plan.
Who's here and People to say hi to
Contract and grant rooms open with one card above the posts. It counts who raised a hand to team, lets a member raise theirs, and suggests up to three people to say hi to, each with one reason. It never shows who is viewing a notice.
3 raised a hand · 2 primes, 1 independent specialist · no sub yet · 1 online now
| Part | Value | Words |
|---|---|---|
| Card | Paper · 1px line · 8px corners · 12px 14px · first thing in the room, above the posts | none |
| Count line | 13.5px ink, parts joined with " · " · the count 700 · the role split muted · the gap in a round #e5ecdb pill · the online count after an 8px #2f7d4a dot · Match-M8 adds muted italic | 3 raised a hand · 2 primes, 1 independent specialist · no sub yet · 1 online now · 1 matched by Match-M8, not confirmed. A grant: lead applicants, partners, no partner yet, no lead applicant yet. A code room: 12 members work in 541519. Nobody yet: Nobody has raised a hand yet · No members list 541519 yet. |
| I'm in as | One joined row, 1px line, 8px corners · label 12.5px muted · choices 36px (44px and full width on a phone), dark olive 600 13px · the chosen one olive with white words · contract and grant rooms only | Prime · Sub · Independent specialist. A grant: Lead applicant · Partner · Independent specialist. |
| People to say hi to | Title Source Serif 4 600 16px · up to three cards, 190px at least, #fdfdf8, 6px corners · 32px initials with a 9px green dot when online · name 600 13.5px, badges 11.5px muted · one reason 12.5px · Say hi olive, 36px (44px on a phone), opens a private chat with a first line ready | People to say hi to · Hide · Prime · SAM lists SDVOSB · Online now · Say hi · Show people to say hi to. First line: Hi Marcus, I saw you raised a hand on this one. Want to talk about teaming? |
| Consent line | 11.5px muted, under the cards, every time | Only members listed in the directory who turned on Suggest me in My Profile. FedM8 never shows who is viewing a notice. |
| Free member | The count line shows; names and cards do not | Names show on Basic. See plans |
| Phone, 640px and under | One line of names replaces the cards; See why opens them | Say hi: Marcus · Example Network Services · Lena · See why · Show less · Hide |
// Who's here goes first in a contract, grant or code room. The room page mounts it:
FedM8Teaming.whosHere(hereHost, ctx, noticeId, {
item: notice, title: notice.title,
onDone: function () { room.reload(); } // after the member raises a hand
});
// Item keys: a notice id, "grant:<id>" for a grant, "naics:541519" for a code room.
FedM8Teaming.tagKind("naics:541519"); // "code"Before your first post
A member with no public name yet sees this card the first time they press Post. It opens inside the box, right above Post, and their words stay where they are. Here a company is posting for the first time.
Talk about the work and who you need. Keep prices, bids and contact details out of open rooms. Share prices only privately with teammates, under a signed teaming agreement. Ask the contracting officer about the requirement, in writing.
Before your first post
People see this next to your post. You can change it any time in My Profile.
Shows as: Example Help Desk LLC
Prime needs a SAM-verified UEI. Add yours later in My Profile.
One quick step before your first post. Check how your name shows, then press Post again. Tick the box too.
3 new posts left today · replies are open
| Part | Value | Words |
|---|---|---|
| Card | #f6f8f1 · edge #cbd4bf · 8px corners · 14px 16px · 560px at most · title Newsreader 600 17px · line 13px muted. In the app a section named by its h3 title. | Before your first post · People see this next to your post. You can change it any time in My Profile. A private chat says "message". |
| Choices | Round, 38px (44px on a phone), white, #b9c4ab edge · chosen: #e4ead8, olive edge, dark olive 600 · not open yet: dashed, #f1f2ee, #7d8778, with the reason linked to it | Post as: Me · My company. A person: What fits you: Just learning · Independent specialist. A company: We team as: Sub · Both · Prime. |
| Name | Box 40px (44px on a phone), white, #b9c4ab edge, 5px corners, 420px at most · the preview under it 13px dark olive 600, read aloud as it changes | Your name or Company name · Shows as: Example Help Desk LLC · Shows as: (type a name) |
| Codes | 38px round chips, each with a checkbox, ticked · the add box 140px | Your codes · 541519 (from sign-up) · Add a code (6 digits, optional) · No codes yet. Add one if you know it. |
| Veteran | Veteran accounts only, ticked from the sign-up answer. Never asked of anyone else. | Show Veteran (self-reported) on my posts |
| Step line | #fbf7ea · edge #d9d2b6 · 6px corners · 13px · just above Post · read aloud (role="status") | One quick step before your first post. Check how your name shows, then press Post again. · Tick the box too. · Saving how your name shows… · Saved. Your posts show as Example Help Desk LLC. |
| Problems | The same line, with focus moved to the field | Enter a name people see, 2 to 120 characters. · A NAICS code is 6 digits. Fix it or leave it empty. · We couldn't save your name. … Your words are still in the box. |
| After the first post | One quiet line with one link | Finish your card so primes can find you. · Finish your card |
// A room's box does this already. For a box of your own:
var fp = FedM8FirstPost.create(ctx, { button: "Post", noun: "post" });
postButton.addEventListener("click", function () {
if (!fp.node.isConnected) form.insertBefore(fp.node, buttonRow); // right above Post
// First press: shows the card and the step line, resolves false.
// Next press: checks and saves the name, resolves true. The words in the box are never touched.
fp.run(statusLine, "Post").then(function (ok) { if (ok) send(); });
});
fp.finish(composeHost); // after the first post: "Finish your card so primes can find you."Talk doors
A Talk door opens a room from anywhere else: a notice card, a grant card, a grant page, a lesson. It says how many posts the room holds and, when known, who is in. Talking is free on every plan, so a door never carries a plan tile.
Sample · Help desk support, Fort Example
Example Command · NAICS 541519
A grant's own page
Sample · Rural IT skills grant
Example Workforce Office · Closes Dec 9
The same row on a phone
| Door | Look | Words |
|---|---|---|
| Talk chip | 34px (44px on a phone) · round · 1px olive edge, no fill · dark olive 600 13px · 14px speech-bubble icon · hover #eef2e6 · count in tabular figures. The one main door on a page may be filled olive. | Talk · 12. Until the count loads: Talk. Read aloud: "Talk about <title>, 12 posts"; signed out: "Sign in to talk about <title>, 12 posts". |
| Who is in | 12.5px muted, right after the chip | 4 in · 1 prime · 2 in |
| Latest words | On a card: a 1px line above, then one line, 12.5px muted, cut with "…" · the name 600 ink · the first sentence, 80 characters at most | Marcus T.: I walked it last year. |
| Grant page row | 44px buttons · 0 16px · 6px corners · 600 14px · Talk olive with paper words; the rest paper with a #81976b edge and dark olive words · hover #eef2e6 · one group named "Talk, team up or watch this grant" | Talk about this grant · 4 · Find a partner · Watch. Signed out: Sign in to Watch one, and to talk about it. Talking is free on every plan. |
| Phone | The grant row sticks 59px from the top, under the header · paper · #dfe5d4 line below · Talk grows to fill the row | Talk · 4 · Partner · Watch |
var TD = FedM8TalkDoors;
var item = TD.itemFor("notice", notice.id); // "grant:<id>" for a grant, "naics:541519" for a code
var door = TD.chip(document, { item: item, title: notice.title, signedIn: !!ctx.user });
cardFoot.appendChild(door); // signed out, the door goes to sign-in, then the room
// One read for the whole list, then every door gets its count:
TD.counts(itemIds, { client: ctx.sb, user: userId }).then(function (map) { TD.fill(list, map); });A room on a phone
On a phone a room fills the screen between the header and the dock. A slim bar gives Back, the room's name and Room info. The box is pinned right above the dock, with the rules line kept to two lines. The sample scrolls inside the frame.
One firm runs a help desk for about 400 people, weekdays 7 a.m. to 6 p.m. Set aside for SDVOSB firms. Offers are due Nov 14.
Has anyone done a site visit at Fort Example? How far is the help desk from the gate?
2 replies
Replies open here.
We're a prime on this one and want a sub for the network side.
Talk about the work and who you need. Keep prices, bids and contact details out of open rooms. Share prices only privately with teammates, under a signed teaming agreement. Ask the contracting officer about the requirement, in writing.
Room info
| Part | Value | Words |
|---|---|---|
| Room bar | Under the 59px header · paper · 1px line below · 4px 2px inside the page's 13px sides · Back 44 × 44 with a 22px arrow in dark olive · the name DM Sans 650 15px on one line, cut with "…" · Room info 44px round, 1px line edge, dark olive Georgia 700 17px | ← (read aloud "Back to Chat", or "Back to NAICS 541519") · the room's name · i (read aloud "Room info") |
| Who's here | The count line, then I'm in as at full width with 44px choices, then one line of names | Say hi: Marcus · Example Network Services · Lena · See why · Hide |
| Pinned box | Held 78px from the bottom, right above the dock · paper · 1px line above · shadow 0 -4px 14px #29372e14 · 8px 12px 10px · rules 12px, two lines at most · box at least 44px, 16px words so the phone does not zoom, and tall enough that the whole placeholder shows · Post 64 × 44 · while writing it grows to 52% of the screen | Ask about this contract, or find a teammate. · Post · Not sent yet (kept in this tab) |
| Sheets | Rise from the bottom · paper · 14px top corners. Room info: shadow 0 -6px 28px #29372e33 · 82% of the screen at most · scrim #1b241e66 · grip 40 × 4 #cdd5bf · title Source Serif 4 600 18px · Close 44px, 64px wide at least · a dialog named by its title. The ⋯ menu: scrim #1d2a2140 · grip #d9ded0 · rows 48px, 15px. | Room info · Contract details · Ask in the VetCert room · NAICS 541519 · View team · Close. The ⋯ menu: Report · Hide this person · People you hid. |
| Targets | Every action, tab, reply toggle, chip and link in a room is 44px tall on a phone | none |
Chat states
Every state says what is true and keeps the member's words. These are the app's own sentences from assets/chat-words.js; use them, never new ones.
Loading
Loading…
Nobody has posted
Nobody has posted yet. Ask a question or share what you know.
Could not load
Chat could not load. Check your connection, then try again.
Heads-up while typing, Why open
This looks like pricing. Share prices only privately with teammates, under a signed teaming agreement.
Rooms on FedM8 are public. Prices, contact details, Social Security and VA numbers, and nonpublic information about a buy stay out, so every member can trust what they read here. The same check runs again when you post.
Refused after Post
We didn't post this. It looks like pricing, and prices stay out of open rooms. Share prices only privately with teammates, under a signed teaming agreement. Your words are still in the box.
Not sent yet (kept in this tab)
Could not send
We couldn't post this. Your words are still in the box. Check your connection, then try again.
Gates: one line, one link at most
Sign in to read and join this conversation.
Set up your Team Up profile to post. Set up profile
You've used today's 3 new posts. You can still reply. New posts open again tomorrow.
Posting is paused on this account. Write to Support and we'll look at it with you. Write Support
Box not ticked
Check the box first. It takes a second.
Remove your own post
Remove your post?
It comes down for good, with any replies under it.
Done: a short toast
Posted.
Reply posted.
Reported. FedM8 will look at it.
| State | Look | In the app |
|---|---|---|
| Loading | One 13px muted line. No spinner, no grey skeleton people. | W.loading "Loading…" |
| Nobody yet | Paper, 1px dashed #cbd4bf edge, 8px corners, 13px muted | W.emptyRoom, W.empty (contract), W.emptyCode(code) |
| Could not load | #fbf4e8 · edge #e3c9a6 · words #5b3a12 13px · Try again olive, 44px | W.readFail; with a draft in the box W.loadFail "Chat could not load. Your message is kept here until you try again." |
| Heads-up | #fbf3dc · edge #e3cf94 · words #5c4708 · "!" in a 20px ring · Edit and Why 30px (44px on a phone) · Why opens the reason under them | FedM8Room.headsUp: checked 0.8 seconds after typing stops, read aloud politely (role="status"). It never blocks Post. |
| Refused | #fbecea · edge #e2b8b2 · words #6d231b · Edit and Why only when the server refused the words | FedM8Room.refusal (role="alert"), words from W.refused |
| Gates | 13px muted, one link at most: dark olive 600, underlined | W.gate(document, message). Never shows a raw code. |
| Field problem | 12.5px #8f2d22 under the field, which is marked aria-invalid | W.ackFirst, W.writeFirst "Write a message first." |
| Remove | Dialog 460px at most · 20px · 10px corners · shadow 0 12px 40px #29372e40 · title Source Serif 4 600 20px · text 13px muted · Remove #8f2d22 with white words | Remove your post? · It comes down for good, with any replies under it. · Cancel · Remove · then "Removed." |
| Toast | Dark olive #344b2c · white 13.5px · 8px corners · 24px from the bottom, centered · leaves by itself | Posted. · Reply posted. · Reported. FedM8 will look at it. · Removed. · Marked as the answer. |
var W = FedM8ChatWords;
// A gate: plain words and at most one link.
host.appendChild(W.gate(document, err)); // "Set up your Team Up profile to post. Set up profile"
// After Post fails: the server's sentence, right above the buttons. The words stay in the box.
form.insertBefore(FedM8Room.refusal(err, { verb: "post", textarea: input }), buttonRow);
// While typing: the heads-up under the box.
var hu = FedM8Room.headsUp(input, { ctx: ctx, item: noticeId });
input.after(hu.node);Do
- Keep the member's words in the box after every failure, and say so.
- Use the server's own sentence for a refusal, with Edit and Why.
- Put one next step in a gate, as one link.
- Ask before anything that cannot be undone, and name what goes.
Don't
- "Something went wrong", a raw error code or a red banner across the page.
- Spinners or grey placeholder people and counts.
- Block Post because of a heads-up. The server decides when someone posts.
- Clear the box when a post fails.
Match-M8
Match-M8 is the product name of the matching AI. Never show an engine or vendor name. Match-M8 says how well a notice fits what a member does, and why, in plain lines. It suggests; the member decides.
- Name
- Match-M8, in every word a member reads or hears: buttons, help, alerts, email, video narration and samples
- Plan
- Basic and Pro · feature id
found_for_youintier.js - Shows
- A percent, the role it fits and up to five reasons
- Drawn by
assets/os-search.js(the match box) withFedM8TeamUpUI.reasons
The match box on a notice
Scored
82% match as a sub
Edit what you do- You fit a key role this work needs
- You do most of this work
- As a sub you could do a major piece
- You have done this kind of work for other customers
- No clearance, license, brand-name or incumbent requirement found
Not scored yet
No Match-M8 score for you on this one yet
Match-M8 scores notices that share your NAICS codes or work terms, every 15 minutes. Check what you do
A Free member
Basic shows how well each notice fits what you do. See plans
On a list card and in Who's here
82% matchDue Nov 14
3 raised a hand · 1 matched by Match-M8, not confirmed
| Part | Value | Words |
|---|---|---|
| Box | #f0f4e8 · edge #cfd8c2 · 10px corners · 16px · headline 700 16px #31553b · reasons 15px ink, a plain bulleted list | 82% match as a sub · for your firm · for you as an independent specialist · to lead it · Edit what you do |
| Reasons | Five at most, built from the member's own answers by FedM8TeamUpUI.reasons(answers, role). Never invented. | You fit a key role this work needs · You do most of this work · As a sub you could do a major piece · You have done this kind of work for other customers · No clearance, license, brand-name or incumbent requirement found |
| Not scored | The same box, a 14px muted note and one link | No Match-M8 score for you on this one yet · Match-M8 scores notices that share your NAICS codes or work terms, every 15 minutes. · Check what you do |
| Free member | One quiet plan line, no box | Basic shows how well each notice fits what you do. See plans |
| Elsewhere | List card foot: 700 #31553b. Who's here: muted italic until the member confirms. | 82% match · 1 matched by Match-M8, not confirmed |
Win Kit: what they paid before
Win Kit answers one question from public award records. It is part of Pro, so its heading carries a P tile. It shows the dollars obligated, never what anyone bid.
What they paid beforeP
The last time this exact work was bought, it was awarded for $1.2M to Example Support Co. (Oct 1, 2021).
Half of these awards were under $640K. The middle half ran from $310K to $1.1M.
Closest past awards
- $1.2M Example Support Co., Oct 1, 2021 Same solicitation number
- $880K Example Systems Group, Mar 3, 2023
- $410K Example Network Services, Aug 19, 2022
From USAspending.gov award records: who won and the dollars obligated. They do not show what anyone bid.
What did they pay before?
Past awards from Example Command under NAICS 541519, last 5 years: 24.
$310KLow
$640KMiddle
$1.1MHigh
These are total dollars obligated per award over its whole life. They are not a yearly rate and not a bid price. Build your price from your own costs, then check it against this band.
Source: USAspending.gov award records. They show who won and the dollars obligated. They do not show who lost or what anyone bid.
| Part | Value |
|---|---|
| Column | Paper · 1px line · a 4px olive top edge (the one colored card top in the app) · 8px corners · 16px 18px |
| Heading | DM Sans 600 16px with a 1px line under it, then the P tile |
| Lines | 15px ink for the answer · amounts 600 #31553b · 13px muted for how to read it and the source · past awards 14px with 1px lines between · "Same solicitation number" in a round canvas tag |
| Band | Three soft cells, 8px corners · 20px 700 #31553b figure over a 13px muted label · Low, Middle, High |
| Honesty | Every view names USAspending.gov and says it does not show bids or losers. USAspending does not publish who lost. |
// The headline and the reasons, as the match box builds them:
var pct = Math.round(Number(match.fit) * 100);
var how = match.basis === "firm" ? "for your firm"
: match.role === "ind" ? "for you as an independent specialist"
: match.role === "prime" ? "to lead it" : "as a sub";
headline.textContent = pct + "% match " + how; // "82% match as a sub"
var lines = FedM8TeamUpUI.reasons(match.answers, match.role); // five at most, from the member's answersDo
- Write Match-M8 wherever a member meets the matching AI: labels, help, alerts, email, narration, alt text and samples.
- Say what Match-M8 used: the member's codes, work terms and answers.
- Show "not confirmed" until the member confirms what Match-M8 added.
- Link to Edit what you do, so the member can fix the inputs.
Don't
- Show an engine, model or vendor name anywhere a member can see or hear it.
- Call a match a chance of winning.
- Invent a reason, or show more than five.
- Show bids or losers. Public award records do not have them.
Plan tiles
A plan tile is a small square right after the name of a paid tool, output or ability: B for Basic, P for Pro. It tells a member which plan the thing belongs to. It informs; it never sells. Free features get no tile. Pro includes AI, so there is no AI tile.
- Files
assets/plan-tile.cssandassets/plan-tile.js- The plan comes from
FedM8Tier.minPlanFor(featureId)intier.js, never typed by hand- Size
- 16 × 16 · 4px corners · DM Sans 700 10px · 6px after the name. A link tile has a 44px hit area.
- Colors
- B: olive
#526547letter, no fill,#b8c5aaedge. P: dark olive#344b2con#e4ead8.
The forms
In context: see it as each plan
Press Free, Basic or Pro. Tiles for a plan the viewer already has turn quiet and stop linking, and the Free line goes away once the plan is there. The samples below change as you press.
| Part | Value |
|---|---|
| Placement | Right after the name, on the same line, 6px away. In a flex row that has its own gap, add plan-tile--flush so the gap is the only space. |
| Link tile | <a> to /plans#basic or /plans#pro · a 44 × 44 hit area around the 16px mark · label on hover or focus: "Basic plan" · read aloud "Basic plan feature. See plans" |
| Inside a control | A <span aria-hidden="true"> tile, and "(Basic plan)" in the control's name: an aria-label that starts with the visible words, or hidden text where the page has a hidden-text class. The control keeps its own action. |
| Word form | plan-tile--word: "Basic" or "Pro", 10.5px 600, for menus and lists with room |
| By a heading | plan-tile--lg: 18px, 11px letter |
| On olive or dark | plan-tile--on-dark: white letter, white edge at 62% |
| The viewer has it | 55% opacity, no link, read aloud "Included in your plan: Basic", label "In your plan" (FedM8PlanTile.apply) |
| Free line | p.plan-lock[data-plan]: one 13px muted line, the tile, one sentence, then "See plans" in dark olive 600, 44px tall. Hidden once the viewer has the plan. No blur, no banner. |
| Feature | Id in tier.js | Tile |
|---|---|---|
| Notices, Grants, Chat | opportunities, grants, chat | none (free) |
| Match-M8 matches with reasons | found_for_you | B |
| Saved searches with alerts | saved_searches | B |
| Bid Coach | bid_coach | B |
| My pursuits | pipeline | B |
| Win Kit and Award Intel | award_intel (Win Kit has no id of its own yet) | P |
| Proposal help | proposal_assist | P |
| Company workspace | company_workspace | none (company seats are not sold) |
<!-- Filled from tier.js; removed when the feature is free -->
Saved searches<a class="plan-tile" data-plan-feature="saved_searches"></a>
<!-- One quiet line where a Free member meets a paid output -->
<p class="plan-lock" data-plan="basic"><span class="plan-tile" data-plan="basic" aria-hidden="true">B</span>Match-M8 matches are part of Basic. <a href="/plans#basic">See plans</a></p>
// In your page's .js file (never an inline script):
var tile = FedM8PlanTile.forFeature("award_intel"); // a link tile, or null when free
if (tile) heading.appendChild(tile);
var inside = FedM8PlanTile.forFeature("saved_searches", { inside: true });
if (inside) {
saveButton.appendChild(inside); // hidden from screen readers
// os.html has no shared hidden-text class, so the button's name carries the plan:
saveButton.setAttribute("aria-label", "Save this search (" + (inside.dataset.plan === "pro" ? "Pro" : "Basic") + " plan)");
}
FedM8PlanTile.apply(root, ctx.plan); // quiets tiles the viewer already hasDo
- One tile per tool, right after its name, on the same line, 6px away.
- Read the plan from
tier.js:data-plan-featureorFedM8PlanTile.forFeature. - Inside a button, tab or link, hide the tile from screen readers and add "(Basic plan)".
- Run
FedM8PlanTile.applywith the viewer's plan so tiles they have go quiet. - Use "See plans" as the only upgrade link.
Don't
- Color a whole button, card or row by plan.
- Shout: Upgrade, Unlock, Go Pro, lock icons, blur or banners.
- Type the plan by hand in page code.
- Put a tile on a free feature, or an AI tile anywhere.
- Two tiles on one tool, or a tile on every line of a paid screen.
States
Every screen says what is true, in words: loading, nothing yet, could not load, saved. One main action per state, then one line that says what it does. No grey placeholder people or counts.
Loading
Loading…
Nothing yet
No pursuits tracked yet.
Could not load
That did not load.
Not sure it was sent
We could not confirm it was sent. Try again; it will not send twice.
Offline
You're offline. Not sent yet. Your words are kept in this tab.
Changed in another tab
This changed in another tab. Reload to see the latest.
Not open
This is not open to you. If someone invited you, check that you are signed in with that account.
This page is not open yet.
Paused or closed, draft kept
This opening is paused. You can still read it. Your draft is kept for when it opens again.
This opening is closed. It is no longer taking responses.
Saved
Saved. Find it on the Saved tab.
A field with a problem
A NAICS code is 6 digits. Fix it or leave it empty.
| State | Look | Rule |
|---|---|---|
| Loading | One 13px muted line | Words only. No spinner, no skeleton people or counts. |
| Nothing yet | Paper, 1px dashed #cbd4bf, 8px corners, 13px muted | Say what is missing. Add the next step when there is one. |
| Could not load, unsure, offline | #fbf4e8 · edge #e3c9a6 · words #5b3a12 · one olive Try again, 44px | The retry sends with the same key, so nothing sends twice. The draft stays in the tab. |
| Not open, paused, closed | One 13px muted line, no button | A paused or closed line keeps the draft. "This page is not open yet." is what a page says while its switch is off. |
| Changed elsewhere | One line and a ghost Reload | Never overwrite newer work without asking. |
| Saved | 12.5px #2f6b3a 600 with a ✓, next to the control that saved | Show it only after the server says it stored the row. |
| Refused | #fbecea, edge #e2b8b2, words #6d231b | The server's own sentence, above the footer, with focus on it. The field it is about is marked. |
| Field problem | 2px ink edge on the field · 12.5px #8f2d22 line under it | aria-invalid="true" and aria-describedby on the field; focus moves to it. |
| Free member | One quiet plan line (see Plan tiles) | Never blur or hide the whole screen. |
Do
- One main action per state, then one line that says what happens ("Keeps it in your pipeline. Nobody is told.").
- Move focus to a refusal or a receipt so it is read aloud.
- Keep drafts through every failure.
Don't
- "Oops", "Something went wrong" or a raw error code.
- Red for anything except a refusal, an error line or a remove button.
- Errors in a toast. A toast only says something is done.
Words
FedM8 sounds like a calm colleague who has done this before: short sentences, plain words, the next step. Words live in one table per file, such as assets/chat-words.js for Chat. Read them from there; never retype them.
- Say what is true, then the next step: "Chat could not load. Check your connection, then try again."
- Write short sentences a busy owner reads once. One idea each.
- Define a term where it appears, in a few words.
- Use the names members know: My Profile, Support, the contracting officer.
- Stay calm: no exclamation marks, no "Oops", no capitals for stress.
- No sales words: unlock, supercharge, don't miss out, exclusive.
- Give the real count or none. Say where a fact comes from: "SAM lists SDVOSB", "Veteran (self-reported)".
- Keep the member's words safe, and say so: "Your words are still in the box."
| Say | Not | Why |
|---|---|---|
| Chat (in the app) · Contract Chat (its public name) | Forum, board, Commons | One name in each place |
| room | channel, group, thread list | Rooms hold posts; posts hold replies. |
| Post · Post reply | Submit, Publish, Send (in a room) | Post is the action word in rooms. A private chat says Send. |
| Helpful · M8 4 | Like, upvote, thumbs up | The writer gets M8. |
| Follow · Following | Subscribe, Watch (in a room) | Watch is for notices and grants. |
| Report · Hide this person · Remove mine | Flag, Block, Delete | Each says exactly what happens. |
| FedM8 AI · not a member | bot, assistant, moderator | The room host never speaks as a member. |
| Match-M8 | any engine, model or vendor name, "the algorithm" | Match-M8 is the product name of the matching AI. |
| Certify (dock) · Get Certified (rail and titles) | Certs, Certification Center | The dock has room for one short word. |
| independent specialist | 1099, freelancer | The word members use for themselves |
| See plans | Upgrade, Unlock, Go Pro | The only upgrade link |
| Sample · Help desk support, Fort Example | real people, companies, emails or phone numbers | Samples are fictional and labelled. |
Accessibility
WCAG 2.2 AA is the floor, and the app's release check allows no serious or critical findings. Most of it comes free with the parts on this page; these are the rules to keep when you build something new.
| Check | Rule |
|---|---|
| Targets | 44 × 44 on a phone for every control. Links inside a sentence are the one exception. |
| Focus | A 2px olive ring (3px on large controls), 2px off the edge, never removed. A focused control is never hidden under the header, a pinned box or the dock. |
| Contrast | Text 4.5:1 at least; field edges, control edges and the focus ring 3:1. See the pairs below. |
| Names | Every icon-only control has a name. When a control shows words, its name starts with them ("Helpful, M8 4. The writer gets M8."). |
| Headings | One h1 per screen, then h2 and h3 in order. A card or sheet title is a heading in the app. |
| Read aloud | Heads-up: role="status", polite. Refusal: role="alert". The first-post step line and toasts: role="status". |
| Keyboard | The ⋯ menu: role="menu", arrow keys, Escape; Tab closes it. Scope tabs: role="tablist", arrows, Home, End. Dialogs and sheets keep focus inside, close on Escape and return focus to the control that opened them. |
| Fields | A visible label on every field; hints and problems tied with aria-describedby; a problem sets aria-invalid and takes focus. |
| Color | Never the only signal: Answered has a ✓ and a word, online has "Online now", a plan has its letter. |
| Motion | No transitions when the device asks for reduced motion. New posts never move the page. |
| Phone | No sideways scrolling at 375px. 16px text in boxes so the phone does not zoom. Pages work at 200% zoom. |
| Pair | Ratio | Use |
|---|---|---|
Ink #29372e on paper #fffef9 | 12.4:1 | Body text |
Muted #586653 on paper | 6.0:1 | Second lines, meta |
Muted on canvas #f5f3ec | 5.5:1 | Notes on the page |
Paper on olive #526547 | 6.3:1 | Main buttons |
Dark olive #344b2c on #e4ead8 | 7.8:1 | Current rail item, the P tile |
Link #435e36 on paper | 7.2:1 | Links |
Placeholder #6a7565 on white | 4.8:1 | Placeholders (never the only label) |
| Olive ring on paper | 6.3:1 | Focus ring |
Field edge #81976b on paper | 3.2:1 | Field edges |
Line #d9ded0 on paper | 1.4:1 | Dividers and card edges only, never the only edge of a field |
Known gap: the Chat boxes still use lighter edges (#c9d1bd in rooms, #b9c4ab on Chat home and the first-post card, about 1.6 to 1.8:1). New fields use #81976b.
For AI agents
Building a FedM8 screen? Read this list, then /design/002/tokens.json, then copy the closest snippet on this page. /design/catalog.json lists every design.
- Use design 002 for the app and every new screen. Use 001 only for brand marks, walkthrough videos, YouTube thumbnails, social posts and print.
- Build with the app's own parts, named in each snippet: the shell in
assets/approved-design.css,FedM8Room.mountfor any conversation,FedM8ChatWordsfor every Chat word. Thex2-classes on this page are for samples only. - Take colors only from the
--fd-*variables. No new hex values, no gradients, no dark theme. - Newsreader (then Source Serif 4) for page and card titles, Source Serif 4 for room titles, DM Sans for everything else.
- One olive button per view. Everything else is a ghost button or a link.
- Every control 44 × 44 on a phone, with a 2px olive focus ring. Check at 1440 × 1000 and 375 × 812.
- Names: Match-M8 for the matching AI, FedM8 AI · not a member for the room host, Contract Chat in public, Chat in the app, rooms, Post. Never an engine or vendor name.
- Plans come from
tier.js. Free features get no tile, and "See plans" is the only upgrade link. - States in words. Keep the member's words after every failure.
- Samples are fictional and labelled Sample. No real people, emails or phone numbers.
- The site's security rules allow no inline styles or scripts, no
styleattributes and no inline event handlers. Styles go in a .css file, behavior in a .js file. - When this page and
DESIGN.mddisagree,DESIGN.mdwins. Say so in Comments.
The core variables
/* assets/approved-design.css sets these on body.fd-design. Read them; do not redefine them. */
body.fd-design {
--fd-bg: #f5f3ec; /* canvas */
--fd-paper: #fffef9; /* cards, header, dock, dialogs */
--fd-soft: #eef1e7; /* quiet fills */
--fd-ink: #29372e; /* text */
--fd-muted: #586653; /* second lines */
--fd-line: #d9ded0; /* card edges, dividers */
--fd-green: #526547; /* the one main button, focus ring */
--fd-green-dark: #344b2c; /* text on light fills */
--fd-mint: #d9eddd; /* count pills */
}Where things live
| Need | Use | File |
|---|---|---|
| Header, rail, dock, buttons, fields | body.fd-design, .btn, .btn.ghost | assets/approved-design.css, assets/approved-design.js |
| A conversation | FedM8Room.mount | assets/fedm8-room.js, assets/fedm8-room.css |
| Chat home | FedM8ChatHome.render | assets/chat-home.js |
| Any Chat word | FedM8ChatWords | assets/chat-words.js |
| A door into a room | FedM8TalkDoors.chip | assets/talk-doors.js |
| Follow | FedM8Follow.button | assets/talk-follow.js |
| Who's here | FedM8Teaming.whosHere | assets/teaming.js |
| Before your first post | FedM8FirstPost.create | assets/first-post.js |
| Plan tiles | FedM8PlanTile | assets/plan-tile.js, assets/plan-tile.css |
| Plan rules | FedM8Tier.can, FedM8Tier.minPlanFor | tier.js |
| Comments on a page | <div class="pc" data-page-comments data-topic="…"> | assets/page-comments.js, assets/page-comments.css |
Comments and questions
Ask a question about this design, or point out something that is missing or wrong. Answers stay here for the next person who builds a screen.