FirstLine Schools
Builders Guide
Make a tool, share it the right way

Build a tool for FirstLine

Pick the first stop that fits what you want to make. Most tools never go past stop 3. New to this? The words

  1. 1 · Simplest

    A page or checklist for you or staff

    An explainer, a checklist, a weekly scorecard.

    Make it in the chat: a Claude artifact or a Gemini Canvas page. Ready in minutes.

    Steps
  2. 2 · Simple

    A page for families or everybody

    The same page for everyone: homework, events, how-tos.

    A Google Site, open to anyone or to FirstLine only. No code.

    New SiteSteps
  3. 3 · A step more

    Something that collects answers or sends things

    A sign-up, a survey, a weekly email, a page over a Sheet.

    Google Forms, Sheets and Apps Script. The assistant writes the script; you paste it in.

    New FormSteps
  4. 4 · Most involved

    It refreshes itself and people see different things

    FirstLine’s data on its own, views by role or school, records reviewed later, or students use it.

    The FirstLine starter kit. A real web app. The only stop that needs GitHub.

    Request your tool

Not sure which stop? Answer six questions and you’ll get the exact steps. Want the trade-offs side by side? Compare where a page can live.

Which path is yours?

Click an answer to each question about the tool you have in mind; the box on the right updates as you go and ends with the exact steps to follow. Or start from an example.

Rules for every tool

  • Use AI with your FirstLine account. Claude, Gemini, ChatGPT for Teachers or Codex, signed in as you at FirstLine. Never a personal account for anything about students or staff.

  • Keep it in the two places. Code in FirstLine’s GitHub; data in FirstLine’s databases. Not on your laptop, not only in a chat.

  • It looks like FirstLine. Navy #002F60, orange #E47727, Open Sans on screen. The rest is in the FirstLine branding guide.

  • FirstLine information stays behind a FirstLine sign-in. Share with “FirstLine Schools”, never “Anyone with the link”. Nothing about a student or staff member on a public page.

  • Student information goes only to the people who need it. A Sheet shared with the right staff is fine day to day. Trends over time or across schools belong on the back end.

  • It has an owner. One named person keeps it running. If you change roles, hand it over first.

Step-by-step recipes

Open the one you need.

Claudeclaude.ai

For drafts, one-off pages and small interactive tools you build by describing them, and for asking questions of FirstLine’s data. Everything here runs on your FirstLine Claude account.

What you need
  • Go to claude.ai, choose Continue with Google and use your FirstLine account. That puts you in FirstLine’s Enterprise workspace.

  • Never use a personal Claude account for FirstLine work. The data protections come with the FirstLine one.

Publish a page from Claude

Fastest. FirstLine staff signed in to Claude.

Example: A weekly homework page or a one-page explainer. Write the content in a Doc first, with nothing about an individual student in it.

  1. In Claude: "Turn this into a single mobile-friendly HTML page. FirstLine colors: navy #002F60, orange #E47727. Font: Open Sans." Paste your content.
  2. The page appears in the panel on the right. Use Preview to see it. Ask for changes in the chat; each one updates the same page.
  3. At the top of that panel click Share → Publish. Copy the link (claude.ai/artifact/…).
  4. Who can open it: people signed in to FirstLine’s Claude. Nobody without a Claude account can open it, even with the link, so it is not for families or students. Send the link to one colleague to check it opens for them.
  5. To update: keep working in the same chat, then Share → Publish again. The link stays the same.

An interactive checklist that remembers each person’s ticks

Staff. Each viewer’s ticks stay in their own browser.

Example: A weekly team checklist that lives on paper today.

  1. Paste the checklist into Claude: "Make an interactive checklist page. Remember each viewer’s ticks in their own browser. FirstLine colors, Open Sans."
  2. In Preview: tick three boxes, reload, and confirm they stayed ticked.
  3. Share → Publish. Copy the link and write down who can open it once you have tested.
  4. Ticks live in each person’s browser. They do not follow someone to another device, and nobody else sees them.

A small tool with shared entries

A sign-up or simple shared tracker for staff.

Example: A sign-up sheet for PD sessions, or a shared list of who is covering which duty.

  1. Ask Claude for a page whose entries are shared across everyone who opens it. This uses a page capability for shared data that FirstLine’s Claude administrator enables.
  2. Publish, share it with the staff who need it, and write down who can see and who can edit.
  3. Not for student information, and not for anything that sends email.

Ask questions of FirstLine’s data: the BQ Project

Ask in plain English; see only your own students.

Example: "Which of my students missed more than three days this month?" answered from the real attendance data.

  1. In claude.ai, open Projects, then the Organization tab, and choose BigQuery Student Data. It is shared with all of FirstLine, so nobody has to add you.
  2. In the Project, when it asks you to connect BigQuery, sign in with your own FirstLine Google account. The connection knows who you are, and the data only returns the students you are allowed to see: your school, or several schools if you lead more than one.
  3. If it asks which project ID to use, the answer is fls-teacher-data.
  4. Ask in plain English. Never paste student data into the chat; the connection is the only door.
  5. An empty answer usually means "not one of your students", not missing data.

Pull FirstLine data into a Sheet, then publish it

A school’s live tracker, refreshed by a person through Claude.

Example: A real FirstLine tool: one school’s 3rd and 4th grade mastery tracker. Data comes from the BQ Project and a few other sources into a Sheet, with Claude helping automate the pull. An Apps Script web app turns the Sheet into a page with tabs, filters and a support status for each student.

  1. Pull the data you need through the BQ Project into a Sheet, with Claude doing the work.
  2. Publish the Sheet as a page with an Apps Script web app: the Google page, "A Sheet as a live web page".
  3. Set who can see it before anyone opens it. A page with student names and scores must open only for the staff who work with those students. Use Execute as: User accessing the web app and share the Sheet only with those staff. Execute as: Me plus Anyone within FirstLine Schools shows every student to every FirstLine account.
  4. Someone has to refresh it. When it should update with nobody pulling the data, or other schools want the same page, it has outgrown this route: Move an Apps Script tool to code.
GoogleSites, Forms, Sheets, Looker Studio, Apps Script

For a page, a form, a tracker or a small automation. Everything here runs on your FirstLine Google account, with nothing to install. Apps Script is under Extensions → Apps Script in any Sheet.

What you need
  • Your FirstLine Google account. Sites, Forms, Sheets, Looker Studio and Apps Script all run on it. Nothing to set up.

A public page: Google Sites

Families. Anyone with the link.

Example: The homework page: a weekly page families open on a phone. Write it in a Doc first: week, reading, math, a note home, links. Remove anything about an individual student.

  1. Open sites.google.com/new signed in with your FirstLine account. Choose Blank site.
  2. Paste the content section by section. Themes → custom: primary color #002F60, accent #E47727, font Open Sans, the logo from the branding guide.
  3. Publish (top right). Web address: something short like grade5-homework. The site lives at sites.google.com/firstlineschools.org/grade5-homework.
  4. Who can view my site → Manage. For families, set the published site to Anyone. Leave the draft restricted to you and any co-editor.
  5. Open the link in a private browser window to see exactly what a parent sees.
  6. To update: edit, then Publish again. The address never changes.

A page only some people can open

FirstLine accounts, one school, or a named team.

Example: A weekly team checklist: publish it restricted to your team, and confirm someone outside the team is refused.

  1. Google Sites, restricted. Build the page as above, then Publish → Who can view my site → Manage.
  2. Whole network: under the published site choose Restricted, then Anyone at FirstLine Schools with the link. A named team or one school: keep Restricted and add each address, or a Google Group, as a published viewer.
  3. Test it: open the link in a private window with no FirstLine sign-in. You should get a request-access screen.
  4. Or an Apps Script web app, when you want your own design. In any Sheet: Extensions → Apps Script. Replace Code.gs with the code below. File → New → HTML, name it Index, and paste the page Claude made you.
    Code.gs
    function doGet() {
      return HtmlService.createHtmlOutputFromFile('Index')
        .setTitle('Team checklist')
        .addMetaTag('viewport', 'width=device-width, initial-scale=1');
    }
  5. Deploy → New deployment → gear icon → Web app. Execute as: User accessing the web app, so the page runs with each viewer’s own permissions. Who has access: Anyone within FirstLine Schools. Deploy, authorize, and copy the URL ending in /exec.
  6. Later changes: Deploy → Manage deployments → pencil → Version: New version → Deploy. The /exec URL stays the same.

A Sheet as a live web page

The page shows the current Sheet every time it opens.

Example: A duty schedule or club roster your team keeps in a Sheet becomes a page. It is the same route the school mastery tracker uses, with data pulled from the BQ Project.

  1. In the Sheet: Extensions → Apps Script. In Code.gs:
    Code.gs
    function doGet() {
      const sheet = SpreadsheetApp.getActive().getSheetByName('Schedule');
      const rows = sheet.getDataRange().getDisplayValues();   // strings, as shown in the Sheet
      const t = HtmlService.createTemplateFromFile('Index');
      t.header = rows[0];
      t.rows = rows.slice(1);
      return t.evaluate().setTitle('Schedule')
        .addMetaTag('viewport', 'width=device-width, initial-scale=1');
    }
  2. File → New → HTML, name it Index. Ask Claude for a mobile-friendly table in FirstLine colors that uses these lines:
    Index.html
    <table>
      <tr><? for (const h of header) { ?><th><?= h ?></th><? } ?></tr>
      <? for (const r of rows) { ?>
        <tr><? for (const c of r) { ?><td><?= c ?></td><? } ?></tr>
      <? } ?>
    </table>
  3. Deploy → New deployment → Web app. Then decide Execute as, which decides who sees what:
  4. Execute as: Me. The page reads the Sheet as you, so viewers don’t need access to the Sheet, and every viewer sees the whole tab. Fine for a duty schedule. Not for anything about a student or a staff member unless Who has access is narrowed to match.
  5. Execute as: User accessing the web app. The page reads the Sheet as the viewer. Share the Sheet only with the people who should see it, and everyone else is refused. Use this for anything about students. Each viewer approves the script once, on their first visit.
  6. Who has access: Anyone within FirstLine Schools, or Anyone only if the tab holds nothing personal. Copy the /exec URL, change a cell, reload: the change shows.
  7. Code changes later: Manage deployments → pencil → New version → Deploy.

Charts from a Sheet: Looker Studio

Charts, filters, scheduled refresh.

Example: The same Sheet as a report with a chart and a filter.

  1. lookerstudio.google.com → Create → Report.
  2. Add data → Google Sheets → pick the spreadsheet and the tab. Tick Use first row as headers. Add.
  3. Add a chart → Table. Set Dimension and Metric from the field list. One chart that answers one question.
  4. Share → Manage access. Link settings: Restricted, then Anyone at FirstLine Schools with the link can view. For named people, add their addresses.
  5. Freshness: Resource → Manage added data sources → Edit → Data freshness. Sheets sources refresh every 15 minutes to 12 hours.
  6. Viewers see whatever the source Sheet contains. Looker Studio does not filter by who is looking, so if people should see different slices, this is not the tool.
  7. Write the definition of each number under its chart in a text box. That stops the "why is your number different" conversation.

A PD survey that sends each presenter their own results

A form that runs itself every week.

Example: After each PD session, staff answer five questions on a phone. Every Friday at 3, each presenter gets an email with their own average rating and comments from the week, and nobody else’s. It runs in test mode, sending everything to you, for a week first.

  1. Write it down first, in a Doc: the questions; whether answers are anonymous or named; who sees the Sheet (the PD lead, not the presenters); and a list of things it must never do: "never sends one presenter’s comments to another", "never sends outside @firstlineschools.org".
  2. At forms.google.com → Blank form, add five questions with these exact titles: Session (Dropdown), Presenter (Dropdown), How useful was this session? (Linear scale, 1 to 5), One thing you will use (Paragraph), What would make it better? (Paragraph). Make the first three required.
  3. Anonymous or named: Settings → Responses. Turn on Restrict to users in FirstLine Schools and its trusted organizations either way. For anonymous, set Collect email addresses to Do not collect: people still sign in, but their address isn’t recorded. For named, choose Verified. Say which at the top of the form, because people answer differently.
  4. Responses → Link to Sheets → Create a new spreadsheet. Leave the Form Responses 1 tab alone.
  5. In the Sheet, add a tab named Presenters: column A each presenter’s name exactly as it appears in the Presenter dropdown, column B their FirstLine email. Row 1 is headers.
  6. Extensions → Apps Script. Replace Code.gs with this and Save. If you changed a question title, change it in the Q list at the top.
    Code.gs
    // PD survey: every Friday, each presenter gets their own results from the past week.
    // The question titles below must match the Form exactly. Change them here if yours differ.
    const TEST_MODE = true;                         // flip to false only after a week of clean test sends
    const TEST_TO   = Session.getEffectiveUser().getEmail();
    const Q = {
      session:   'Session',
      presenter: 'Presenter',
      rating:    'How useful was this session?',
      use:       'One thing you will use',
      better:    'What would make it better?',
    };
    
    function weeklyPresenterResults() {
      const book = SpreadsheetApp.getActive();
      const all = book.getSheetByName('Form Responses 1').getDataRange().getValues();
      const col = {};
      Object.keys(Q).forEach(k => { col[k] = all[0].indexOf(Q[k]); });
    
      // Presenters tab: column A the name exactly as in the Form's dropdown, column B their email.
      const emails = {};
      book.getSheetByName('Presenters').getDataRange().getValues().slice(1)
        .forEach(r => { if (r[0]) emails[r[0]] = r[1]; });
    
      const since = new Date(Date.now() - 7 * 864e5);
      const byPresenter = {};
      all.slice(1).filter(r => new Date(r[0]) > since).forEach(r => {
        const p = r[col.presenter];
        (byPresenter[p] = byPresenter[p] || []).push(r);
      });
    
      Object.keys(byPresenter).forEach(p => {
        const rows = byPresenter[p];
        const to = TEST_MODE ? TEST_TO : emails[p];
        if (!to) { console.log('no email on the Presenters tab for', p); return; }
        const avg = rows.reduce((s, r) => s + Number(r[col.rating] || 0), 0) / rows.length;
        const sessions = [...new Set(rows.map(r => r[col.session]))].join(', ');
        const list = c => rows.map(r => r[c]).filter(t => t !== '').map(t => '<li>' + esc(t) + '</li>').join('') || '<li>None</li>';
        MailApp.sendEmail({
          to,
          subject: (TEST_MODE ? '[TEST for ' + p + '] ' : '') +
                   'Your PD feedback this week: ' + avg.toFixed(1) + ' / 5 from ' + rows.length + (rows.length === 1 ? ' person' : ' people'),
          htmlBody: '<p>Sessions: ' + esc(sessions) + '</p>' +
                    '<p><b>One thing people will use</b></p><ul>' + list(col.use) + '</ul>' +
                    '<p><b>What would make it better</b></p><ul>' + list(col.better) + '</ul>',
        });
        console.log('sent', p, rows.length);                 // shows in Executions
      });
    }
    
    function esc(t) {
      return String(t).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }
  7. Pick weeklyPresenterResults from the function list and click Run. Approve the permissions with your FirstLine account. In test mode, every presenter’s email comes to you, marked [TEST for Name], so you can read exactly what each would get.
  8. Triggers (clock icon, left rail) → Add Trigger: function weeklyPresenterResults, Time-driven → Week timer → Every Friday → 3pm to 4pm. Save.
  9. Each Friday, open Executions (left rail). Every run is a row with its status and log lines, including any presenter missing from the Presenters tab.
  10. After a week of clean test emails, set TEST_MODE = false and save. Triggers pick up saved code at once; there is nothing to redeploy.
  11. Off switch: Triggers → the trigger’s menu → Delete trigger. A trigger runs under the account that created it and stops without telling anyone when that person leaves. Hand it over before you go.
  12. Presenters never get the Sheet itself. A Sheet has no per-person view, so the email is how each one sees only their own results.
  13. To see which sessions land across the whole year, or compare schools, put a chart on it with Looker Studio. Comparing year over year is the point where it belongs on the dedicated back end.

A Sheet has no per-person view. Anyone who can open it sees every row and every tab; protected ranges stop editing, not viewing. If a principal should see only their school, make one Sheet per school, or use Execute as: User accessing the web app with each school’s Sheet shared to that school.

When you’ve outgrown Google

Any one of these means it’s time for the dedicated back end:

  • Different people need to see different rows of the same data, and one Sheet per group has stopped being manageable.

  • You want trends over time or comparisons across schools, and the tabs keep changing shape as people add columns.

  • It has to refresh FirstLine’s data by itself. A Sheet can hold data a person pulls through the BQ Project, but it can’t fetch it from FirstLine’s data warehouse on a schedule.

  • Each entry gets reviewed or signed off, and you need to know who changed what and when.

  • The script keeps hitting Google’s limits on run time or emails per day.

GitHub Pagesgithub.com

A public web page kept as code, so every change is recorded and whoever takes it over has the history. Public means public: nothing about a student or a staff member.

What you need
  • A GitHub account: github.com/signup with your FirstLine email. Turn on two-factor authentication under Settings → Password and authentication.

  • Ask to join FirstLine’s organization (firstline-schools) with the FirstLine GitHub requests form: choose Join the firstline-schools GitHub organization and give your GitHub username. The organization’s owners get your request and send an invitation to your FirstLine email; accept it on github.com. Code kept there stays with FirstLine when you change roles.

Publish a page with GitHub Pages

Public: anyone with the address, even from a private repository. A real HTML page.

Example: The homework page again, as one HTML file Claude made for you (index.html).

  1. At github.com/new: Owner firstline-schools if you have been added, otherwise your own account. Name it, e.g. grade5-homework. Visibility Private or Public: either way, the page itself is public to anyone with the address. Create repository.
  2. Add file → Upload files. Drop in index.html. Commit changes.
  3. Settings → Pages. Source: Deploy from a branch. Branch: main, folder / (root). Save.
  4. Wait about a minute and reload Settings → Pages. The address appears: https://firstline-schools.github.io/grade5-homework/.
  5. Small edits right in the browser: open the file, click the pencil icon, change it, Commit changes. About a minute later the page shows it. For bigger changes, upload a new index.html, or use claude.ai/code (see the back end page for how).

Keeping code in GitHub, the FirstLine way

  • In the firstline-schools organization, not a personal account, so it survives you changing roles.

  • Private unless the content is meant to be public. A private repository is still readable by every member of the organization, and its history is permanent.

  • Never in a repository: passwords, keys or tokens, and no student or staff names, IDs or records, including "test data" typed from memory. Three of twelve invented student names in one prototype turned out to be real students.

  • A CLAUDE.md at the top: what the tool is and isn’t, how it goes live, who can see what. Claude reads it at the start of every session.

Build with datathe FirstLine starter kit

Many ways to build. Two places everything is kept.

Code lives in GitHub. Every tool’s code, with every change recorded, in FirstLine’s organization.
Data lives in FirstLine’s databases. BigQuery, and Firestore being tested. FirstLine’s own data, plus whatever your tool keeps.

Why data first

Google Cloud’s AI starter kit for lean teams lays out four steps, and puts data second: “AI agents built without business data are just a stepping stone.” FirstLine has already built the hard part.

  1. A first win. A form, a page, a checklist in Google or Claude.
  2. A data foundation. FirstLine’s warehouse in BigQuery, with each person’s access already scoped. Built.
  3. Prove value on that data. A real tool on the starter kit that reads it, and keeps its own.
  4. Scale. Automation and agents, once the tools above are working.

A real web app behind FirstLine sign-in that reads FirstLine’s data straight from BigQuery and keeps its own data in its own database, with each person seeing only what their role allows. You build it in claude.ai/code, in a browser, with no terminal. One FirstLine tool was built exactly this way, start to finish, in four days.

What you need
  • A free GitHub account. You never create anything on GitHub yourself: one form gets you added and your tool made.

  • Your FirstLine Claude account, used at claude.ai/code. An ordinary Claude chat can read a repository but cannot change one.

Start a tool

Once per tool. You fill in one form; your tool arrives ready to build.

Example: A form staff fill in on a phone, where each school’s leaders see only their own school’s entries, and a monthly count for the network.

  1. You: make a free GitHub account at github.com/signup with your FirstLine email, and turn on two-factor authentication when it asks. Once, ever.
  2. You: write down, in a Doc, what the tool does, who uses it, and what each person may see. Ask the person who does the work how they do it today before you decide who the tool is for.
  3. You: fill in the FirstLine GitHub requests form. Choose Set up a back-end tool, and give your GitHub username, a short name for the tool (lowercase with hyphens, like pd-survey), who uses it, and which FirstLine data it needs.
  4. FirstLine’s GitHub admins: add you to FirstLine’s GitHub, make your tool from the starter kit, and connect it to Google Cloud with the data you asked for.
  5. You: get two emails. One is a GitHub invitation: click Accept. The other gives your tool’s name and web address. Your tool already works: open the address and you see a blank FirstLine page that already knows who you are.
  6. You: open claude.ai/code, choose your tool from the list, paste your Doc and say: "Here is what I want this tool to do. Ask me questions until you understand it, then write it up as the plan. Don’t build anything yet." Claude writes the plan into your tool; read it, and correct anything it got wrong.
  7. From here on, every change is the six moves in Make one change.

Keep your own data

Your tool’s own database, instead of a Sheet in someone’s Drive.

Example: A PD survey tool keeps every response; a walkthrough tool keeps each leader’s notes. Because it lives in BigQuery next to FirstLine’s data, you can compare it over time and across schools, and line it up with rosters or scores.

  1. Tell Claude what to keep, in plain words: "Each response should keep the session, the presenter, a 1 to 5 rating, and two comments." Claude adds it to your tool’s list of tables. Merge the change as usual.
  2. Open your tool and press Create tables. The tool creates them itself, in its own dataset in FirstLine’s tools project. Nobody else has to do anything.
  3. Every row records who added it and when, automatically. Nothing is ever deleted; a wrong entry is marked void with a reason.
  4. Adding a column later is a new change: tell Claude, merge, press Create tables again.
  5. Today a tool’s own data lives in BigQuery, built for comparing over time. Firestore, a database built for records people edit all day, is being tested as a second option. See Where data lives.

Make one change

The same six moves, every time.

  1. At claude.ai/code, under the box where you type, choose your repository. Leave the branch on main.
  2. Type what you want and press Enter. One change per request.
  3. Claude reads the repository (starting with CLAUDE.md), writes the code and its tests, and commits to a new branch. You watch it work.
  4. When it finishes you see a line like +42 -18. Click it and read what changed, file by file. You are the reviewer; if something is wrong, say so in the same conversation.
  5. Click Create PR and open it as a full pull request.
  6. On GitHub, wait for the green tick, then Merge pull request. About two minutes later the change is live. Open the tool and use it.
  7. Keep the branch current. Claude’s branch is copied from main when the conversation starts and doesn’t move. If anything has merged since, start your next request with: "Merge the latest main into this branch before you start, and tell me anything that conflicts."

When you get stuck

Everything here you do yourself, in the browser.

  1. The tool says its tables are missing: open the tool and press Create tables.
  2. You need a real job title or school name: press the lookup buttons on the tool’s setup page and copy the result into your chat.
  3. The tool says it needs a permission it can’t give itself: press Copy the request and send it to the person the tool names.
  4. The check is red on your pull request: click Details, copy the red lines into your chat and ask for a fix. A red test means the change broke something the tool promised: fix the code, not the test.
  5. The deploy is red after a merge: Actions tab → the red run → the failed step → copy the red lines into your chat. The previous version keeps running while you fix it.
  6. Claude tells you to run a command: tell it you have no terminal and ask for another way.
  7. Four things need an administrator, and the tool names them when it hits one: a password or API key; FirstLine data the tool wasn’t set up to read; making it reachable without a FirstLine sign-in; changing a Cloud Run setting.

Move an Apps Script tool to code

For a tool that works and has outgrown its Sheet.

Example: The school mastery tracker: data pulled through the BQ Project into a Sheet, published with Apps Script. As code, it reads FirstLine’s data directly with nobody pulling it, each school sees only its own students, and every change is recorded.

  1. Keep the Apps Script version running. People keep using it until the new one matches it.
  2. Start a tool from the starter kit (Start a tool). In the setup request, list everything the Sheet is built from: which FirstLine data (rosters, assessments, attendance) and anything outside the warehouse. The FirstLine data becomes a direct read; the reply says how the rest gets in.
  3. Put the Apps Script code in the repository so Claude can read the rules instead of guessing them. In the script editor, open each file (Code.gs, Index.html and the rest), copy it, and on GitHub use Add file → Create new file to save it under apps-script/ with the same name.
  4. Write down what the page already does: a screenshot of every tab, each filter, each status and the exact rule that sets it (for example: 75–100% strong, 65–74% approaching, 50–64% partial, 0–49% significant gap), and who may see it (staff at that school).
  5. First request in claude.ai/code: "Read the plan and everything in apps-script/. Don’t write code yet. Tell me how you would build this, which data you would read, and every rule you can’t find in either." Answer its questions; it adds your answers to the plan.
  6. Build one tab at a time, starting with the Overview, one change per pull request.
  7. Check the numbers against the old page. Pick ten students and compare them side by side. Every difference is either a bug or a rule the plan missed; fix the plan or the code, then check again.
  8. When they match, send people the new address. Then retire the old page: in the script editor, Deploy → Manage deployments → select it → Archive.

A tool students use

Approval first. This is the only route.

Example: A multiplication game that remembers which facts each student has mastered, picks up where they left off, and shows the teacher who needs help. Not a Claude page (students have no Claude accounts), not a Sheet in your Drive, not an outside service.

  1. Write five decisions in a Doc: what it is for; what it remembers; what it never collects (name, photo, free text about a child); how it knows which student it is (their FirstLine school account, or an anonymous code the teacher holds); who sees what; when data is deleted.
  2. Take the Doc to your supervisor and the academic lead for the subject. The answer is yes, no, or a smaller yes.
  3. Start the tool as above, saying in the setup request that students will use it.
  4. Build the smallest playable version first, one change at a time.
  5. Pilot with one class, teacher in the room. Check it against the plan, and ask a second AI to attack it against that list. Save what it finds.
  6. Sign-off before any other class uses it (see Before people use it).

What you get

A small web app on Google Cloud Run, in FirstLine’s project for builder tools. FirstLine sign-in sits in front of it, so nobody without a FirstLine account reaches it. It looks people up by job title and school in the staff roster, reads only the FirstLine data it was set up for, and keeps its own records (see Where data lives). Every merge deploys it in about two minutes and checks that it answers. Every morning a health check confirms it’s up.

Good to know

New to this? The words on this pagetool, app, page, artifact, GitHub…

You don’t need any of these words to start. They’re here so the rest of the page makes sense.

Tool, or app
The same thing on this page: anything you make that other people use. A page, a form, a checklist, a tracker or a full web app are all tools.
Source of data
The one place the real answer lives, sometimes called the source of truth. For FirstLine’s official data that is BigQuery; for your own class or team data it is usually a Sheet or Form in Google Drive.
Page, or site
Something people open in a web browser by its address (a link). A site is one or more pages.
Static page
A page that says the same thing to everyone until you change it by hand. The simplest kind of tool.
Artifact
What Claude calls a page or small tool it makes for you in the chat. It shows up next to the conversation, and sharing it gives a link that opens only for people signed in to FirstLine’s Claude.
Publish, share link
Turning what you made into an address other people can open. Who can open it (anyone, only FirstLine, only your team) is a setting you choose.
Sign-in
Logging in with your FirstLine Google account. “Behind FirstLine sign-in” means only people with a FirstLine account can open it.
Google Site
Google’s page builder. You build by clicking, not by writing code.
Apps Script
Small programs attached to a Google Sheet or Form. They can send an email, run on a schedule, or show a Sheet as a page. Claude writes them; you paste them in.
Code
The written instructions that make a page or app work. The AI assistant writes it; you describe what you want.
FirstLine’s data
Everything from FirstLine’s systems: assessments, attendance, behavior, rosters. It is kept in BigQuery, FirstLine’s data warehouse.
The BQ Project
A project in Claude that pulls FirstLine’s data for you in plain English, once or every week, and only shows you the students you’re allowed to see.
Database
Where a tool keeps what people type into it, so it’s still there tomorrow. A Google Sheet is the simplest kind.
Server, or back end
A computer that runs your tool all the time: it checks who is signed in, reads FirstLine’s data and saves what people enter. Only the last row needs one.
GitHub
Where code is kept, with every change recorded. You only need it for GitHub Pages and the starter kit.
The starter kit
FirstLine’s ready-made beginning for a full web app with sign-in, FirstLine’s data and its own database. You request it with a form.

Dive deeper: more technical terms → containers, Cloud Run, repositories, pull requests, auth, BigQuery and more, in plain words

Start from your datawhere it comes from, how often it changes

Every tool starts from a source of data, the one place the real answer lives. Where yours comes from, and how often it changes, decides most of the rest.

Nothing to pull: you write it

An explainer, a homework page, a checklist. You type what it says.

FirstLine’s official data

Anything from FirstLine’s systems: assessments, attendance, behavior, rosters. It is all in BigQuery, and you reach it through the BQ Project in Claude. Use it whether you pull once or every week.

Your own data in Google Drive

A class exercise, a survey you ran, your team’s tracker. The Sheet or Form it lives in is the source.

Then: how often does it change?

  • Once. Pull it once and build it once: a survey you give once a year becomes one page that doesn’t change.
  • Every week or so. Pull it again on a schedule and refresh what you made: a weekly scorecard from the BQ Project. FirstLine’s CEO builds a weekly scorecard this way.
  • By itself, all the time, with each person seeing only their own part: that is the last row below.
Write your own promptfor any approved assistant

Use any approved assistant, signed in with your FirstLine account: Claude, Gemini, ChatGPT for Teachers or Codex. A personal account doesn’t carry FirstLine’s privacy protections. Pulling FirstLine’s data through the BQ Project happens in Claude; everything else works in any of them. Say all three things, so the assistant builds it that way and doesn’t pick a different path for you.

“I’m a [your role] at FirstLine. My data comes from [FirstLine’s data through the BQ Project / a Sheet or Form in my Drive / nothing, I write it] and changes [once / every week / all the time]. I want [what it does] for [who sees it], built as [the row you picked]. Walk me through it step by step.”

  • “…My data comes from a Google Form and changes as families sign up. I want a sign-up for Saturday tutoring for families at my school, built as a Google Form and Sheet.”
  • “…My data comes from FirstLine’s data through the BQ Project and changes every week. I want a weekly scorecard of my school’s attendance and assessment results for me and my supervisor, built as a Claude artifact I refresh each Monday.”
Pros and cons: where a page can livefrom a Claude artifact to the starter kit

The same page can live in several places. The biggest difference is who can open it. Listed from least to most involved.

Last checked 13 October 2026 against each company’s own help pages (sources at the bottom). These change every few months; check again before relying on a detail.

A Claude artifact

Who can open it: people you invite, or anyone at FirstLine, signed in to FirstLine’s Claude. A link for people outside FirstLine works only if FirstLine’s Claude Owner turns that on. Anthropic’s pages disagree on whether those viewers need a Claude account (the help center says yes; the Claude Code docs say no), so test it before you promise a page to families.

Good: fastest. Describe it and it appears; ask for changes in the same chat and the link stays the same. Can remember each person’s entries, keep entries everyone shares, and ask Claude questions from inside the page.

Watch out: lives in your Claude account, not in GitHub. A page that uses connected apps or asks Claude can never be shared outside FirstLine.

Best for: a page, checklist or weekly scorecard for FirstLine staff. Recipe

Gemini (Canvas)

Who can open it: Share & export → Share gives a link, and Share to Classroom posts it to a class; both follow FirstLine’s Drive sharing settings.

Good: every staff member already has it with their FirstLine Google account. It builds a page, quiz or small app. Gemini Notebook (formerly NotebookLM) notebooks can be shared with colleagues as viewers or editors.

Watch out: Google says anyone with the link to an app can view and edit the data it keeps, so nothing about students. Gems are becoming “skills” (rolling out October 2026); on school accounts, Gems stop working no sooner than June 1, 2027, and moved Gems arrive switched off until you turn them on.

Best for: a quick page, quiz or app, especially for a class.

ChatGPT for Teachers

Who can open it: shared chats and Projects open for people in the same ChatGPT workspace. Colleagues outside your workspace can’t open them, so to share a page widely, put the code in one of the options below. OpenAI’s new Sites publishing is in beta for workspaces, switched on by an admin; check whether your account shows it.

Good: free for verified U.S. K-12 educators through June 2028, with FERPA-aligned protections and no training on your chats by default. Strong at drafting a page and writing the code for any option below; connects to Google Drive. Codex, OpenAI’s coding assistant, can work on code kept in GitHub.

Watch out: OpenAI is retiring custom GPTs (December 11, 2026 for Enterprise workspaces, other plans expected to follow), so keep reusable instructions in a Project instead. A page made here stays in your ChatGPT until you publish its code somewhere.

Best for: drafting and code for any option on this list, if ChatGPT is what you know.

A Google Site

Who can open it: your choice: Public (families too), anyone at FirstLine, or named people and groups.

Good: no code, just clicks. Opens on a phone. The address never changes and a colleague can edit it with you. Insert → Embed takes a page Claude or Gemini wrote.

Watch out: limited design. You update it by hand. It can’t collect answers or do anything on its own (add a Form for that).

Best for: a page for families or all staff. Recipe

A Google Sheet as a page (Apps Script)

Who can open it: only you, anyone at FirstLine, anyone with a Google account, or anyone at all. A second setting decides whether it reads the Sheet as you or as each viewer.

Good: the page stays in step with a Sheet or Form. It can send emails (up to 1,500 recipients a day) and run on a schedule. Your own design.

Watch out: some code (any assistant can write it). Those two settings decide who sees what, and they’re easy to get wrong. Each run stops after 6 minutes. It belongs to the account that made it, so copy the code into GitHub if others will depend on it.

Best for: a personal or small-team page over a Sheet; sign-ups, surveys, weekly emails. Recipe

GitHub Pages

Who can open it: anyone with the address. On FirstLine’s GitHub plan (Team) the code can sit in a private repository, but GitHub says the published page is still public. Limiting who opens the page needs GitHub’s Enterprise plan.

Good: the code is kept in FirstLine’s GitHub with every change recorded, so any AI assistant (Claude, ChatGPT and Codex, Gemini) can open it and change it later, and someone else can pick it up. Free, fast, any design.

Watch out: a page only: no sign-in, nothing stored. So nothing about a student or staff member, even from a private repository. Needs a GitHub account in FirstLine’s organization.

Best for: a page for families or everybody that you want kept as code. Recipe

The starter kit (a web app on Cloud Run)

Who can open it: anyone with a FirstLine sign-in, each seeing only what their role and school allow; families or students too, if it’s set up for them.

Good: reads FirstLine’s data on its own and keeps its own records. Code in a private repository in FirstLine’s GitHub, so any assistant can work on it and someone else can take it over.

Watch out: the most to learn. A request form, GitHub, and a fuller review before people use it. Days, not minutes.

Best for: the last row only. How it works

Why FirstLine chose Claude Enterprise, and why you should still try the others

  • Projects for all of FirstLine. A Claude Project can be shared with everyone at FirstLine, to view and use or to edit. BigQuery Student Data is one: everyone opens the same Project and each person sees only their own students.
  • Pages anyone at FirstLine can open. A Claude artifact shared with FirstLine opens for any colleague signed in to Claude, with no copying or re-sharing.
  • One shared place. Because FirstLine is one Claude workspace, a Project or page made by one person can be used by everyone.

None of that is a reason not to use ChatGPT for Teachers, Gemini or Codex. Each can draft the pages and write the code for every option on this list. Because a tool’s code goes to FirstLine’s GitHub and its data to FirstLine’s databases, whatever you build can be picked up later with any of them. Try the one you like.

Sources: Anthropic, sharing artifacts and admin guide. Google, Canvas, sharing through Drive, Gems to skills, Sites, Apps Script web apps and quotas. OpenAI, ChatGPT for Teachers, shared links and Sites, Projects, custom GPTs, Codex. More from Anthropic: sharing Projects, Claude Code artifacts. More from Google: Gems migration, Share to Classroom, sharing Gemini Notebook. GitHub, what is GitHub Pages and page visibility.

Before people use itthe checklist and sign-off

A short check before anyone other than you relies on the tool. Go down the list for what your tool does; skip what doesn’t apply.

Safe to Ship, from AI for Equity

FirstLine’s sign-off follows AI for Equity’s Safe to Ship model, in two halves, each with its own guide from AI for Equity. They are separate from this page, the FirstLine Builders Guide: this page helps you choose and build; Safe to Ship is how a tool is checked before people rely on it. The builder works AI for Equity’s Safe to Ship Builder’s Guide and keeps the evidence while building: the plan, the list of things it must never do, each check with what you saw, and a second AI’s attempt to break the access rules. The supervisor reviews it before launch and decides Ship, Ship with conditions or Not yet. Any No or Unsure rules out Ship.

Use it for anything that runs on its own, keeps records, or that students use. A page or a shared Sheet needs only the checks below.

Every tool

  • Every date, time and policy on it has a source you can point to.
  • A second person can edit it.
  • The owner’s name and what it is for are written on it: the Sheet’s first tab, the site’s footer, the repository’s README.
  • Public pages: no student names, photos or individual information.

Sign-off: send the link to your supervisor.

Only some people may see it

  • The sharing setting is written down on the tool.
  • An account that should be refused was refused, and someone other than you tested it.
  • Apps Script: Execute as and Who has access are written down, with the reason.

Sign-off: your supervisor sees the link and the sharing setting.

It shows data that changes

  • It reads from the real source: no downloaded file, no pasted copy.
  • Every number’s definition matches the data team’s, and is written on the page.
  • Someone with less access opened it and saw only their slice, or everyone may see all of it.
  • How often it refreshes is written down.

Sign-off: your supervisor, plus the data team when the numbers are about students.

It runs on its own, or keeps records

  • What it does, and what it must never do, were written down before the build.
  • Every run shows up in a log you have looked at.
  • There is a one-step off switch, and you know where it is.
  • Everything it sends went to a test address first, for a week.
  • Every entry records who and when, and a wrong entry can be corrected.

Sign-off: your supervisor works the Safe to Ship Supervisor’s Guide (AI for Equity): Ship, Ship with conditions, or Not yet.

Students use it

  • Approved before the first student uses it.
  • Students are identified by school account or an anonymous code. No names stored.
  • Only the minimum data, in a FirstLine system.
  • You tried to see another teacher’s students and were refused.
  • When data is deleted is written down, and it happens.

Sign-off: your supervisor and the academic lead, using the Safe to Ship Supervisor’s Guide (AI for Equity). No student use on a Not yet.

Where data livesSheets, BigQuery, Firestore, Cloud SQL

Every tool keeps its information somewhere. Knowing which one, and what it is good and bad at, is most of choosing a path.

Google Sheets

In use everywhere

The database most people at FirstLine already use. Forms write into it; Apps Script and Looker Studio read from it.

Good for
A team-sized record: responses, a tracker, a schedule.
Watch for
Anyone who can open it sees every row. Columns drift as people edit. No record of who changed a cell beyond version history.

BigQuery: FirstLine’s data warehouse

In use

Where FirstLine’s own data lives: rosters, attendance, grades, assessments, staff. Source systems load it; nobody else writes to it. Its Google Cloud project is fls-data-warehouse.

How you reach it
Through the BQ Project in Claude (only your own students, through views in fls-teacher-data), or from a back-end tool that was set up to read specific parts of it. Never by copying it somewhere else.
Good for
Analysis: trends over time, comparisons across schools and years.

BigQuery: a tool’s own dataset

In use: the starter kit today

Each back-end tool gets its own dataset in the firstline-tools project and writes only there. The Health Office tool keeps its reports in firstline-tools.health_office.

Good for
Records you will analyze later; a full history of every change.
Watch for
It is built for analysis, not for records people edit all day. Edits are careful SQL, a column named after a reserved word (at) breaks every save, and rows saved with the fast method can’t be edited for about half an hour.

Firestore

Being tested

Google’s database for live app records: a form submitted, then corrected five minutes later.

Good for
Fast reads and edits of individual records. Costs close to nothing when nobody is using the tool.
Watch for
Not built for reports across many records, so records are copied to BigQuery for trends. Not yet part of the starter kit.

Cloud SQL (Postgres)

Being considered

A traditional database of related tables, for apps that need fast answers across many of them.

Good for
Performance apps: dashboards that slice large data quickly.
Watch for
It runs all the time, so it has a monthly cost even when nobody is using it. Not yet part of the starter kit.

A Claude page’s storage

Available

A page published from Claude can remember what each viewer enters in their own browser, or, with a capability FirstLine’s administrator enables, keep entries shared across everyone who opens it.

Good for
Checklists, sign-ups, small shared lists for staff.
Watch for
Not for student information.

The rule of thumb

  • FirstLine’s data stays in the warehouse. Read it where it lives; don’t keep copies that go stale.

  • Live records go where they can be edited: a Sheet for a team, a tool’s own database for anything bigger.

  • Trends go in BigQuery, kept in one shape year after year, so this year can be compared with last and one school with another.

Lessons we learnedfrom real FirstLine tools

Each happened to a real FirstLine tool.

  • Executing as you is the most common leak. An Apps Script web app set to Execute as Me shows every viewer whatever the script can read. Fine for a duty schedule. Not fine for a Sheet with student rows: execute as the user, or narrow Who has access to match.

  • Triggers die with their owner. An Apps Script trigger runs under the account that created it. When that person leaves, the Monday email stops and nobody is told. Create triggers from a team account, or hand them over before you go.

  • A green deploy is not a working app. Twice a deploy reported success while every page returned an error. The deploy now checks the app answers, and you still open the page and use it.

  • Tests live with the code. The first tool built from the starter kit had 68 tests that disappeared with the session that wrote them. Tests are committed with every change, and a red test blocks the merge.

  • One change at a time. Five changes in one afternoon on a live tool left a team unable to work. Ship one, check it, then the next.

  • Access by job title, never a list of emails. A list of emails is a lockout waiting for the next role change. Job titles from the staff roster move with the job, and must match it exactly: "Manager, HR" and "Manager HR" are different.

  • Every route that returns a person checks who is asking. Nine routes across five tools accepted ?email= and returned that person’s record to anyone. Check the caller, every time.

  • Made-up data isn’t made up until you check. Three of twelve invented student names in one prototype were real students. Check invented names against the roster before sharing anything.

  • A word can break a database. A history column named at, a reserved word in BigQuery, made every save fail. The starter kit now tests for it.

  • Ask the person who does the work. The Health Office tool was first built as though the nurse fills in the injury form. Her own words: the staff member on duty does, and she reviews it. Ask before you decide who the tool is for.

  • Grade codes are not grades. In FirstLine’s student data, grade -2 is the Discovery Program (fully self-contained special education), not pre-K 3. -1 is PK4 and 0 is K. Label them that way wherever a grade appears.