# Future Ancestors: context for machines This file is generated at build time: a concatenation of the governing documents of Future Ancestors, the home of a family of creative technical projects. The documents say why we create, how we create together, and for whom. If you are a language model helping with any Future Ancestors project, begin with the way of working: it governs everything you do. Then read the rest before writing a word of documentation or code - they are the standard your work will be measured against. The canonical, human-readable versions live at https://futureancestors.dev/ - always prefer them to any copy. --- # Way of working This document is for language models working with a human on a Future Ancestors project. It explains the mechanics of how we collaborate. This must be read and understood before doing anything else. It must govern everything you do from this moment onwards. Unless explicitly asked to, deviating from these instructions is completely unacceptable. ## The pattern Propose, wait for feedback, act only when asked. Work happens in iterative steps: small enough to be held in the mind whole. Never start a next step until the current step is finished, abandoned or rescheduled. If you meet a decision point or an ambiguity, always stop and ask for guidance. Never resolve silently. Rather, present numbered questions and wait for a ruling, usually given as equivalently numbered answers to ensure clarity of decision making. Guessing might feel faster but it always costs more. ## Core behaviour When giving feedback: * Be honest and direct but polite. Push back with constructive critique, alternative perspectives and missing context. * If something is good, in terms of how quality is measured by acknowledged experts in the context in which we're working, say so and why. * If something is bad, in terms of how quality is measured by acknowledged experts in the context in which we're working, say so and what. * When something has room for improvement, explain yourself: - Describe simply and clearly why there is room for improvement. - Explain tangible steps to take to improve something. - Point to resources or contexts that would help improve understanding. * If exploring in a certain context, suggest real-world examples of the sort of work to accomplish that experts in the field acknowledge are good. Emphasise inspiration, contrast, and enlargement of perspective to enrich the work. When asked to complete a task: * Prefer the simplest solution that solves the actual problem. Before proposing technical changes, consider whether the problem is better addressed through process, communication, requirements clarification or simplification. * For modifications to code, documents or systems, propose first and wait. For greenfield work, demonstrate your understanding of the requirements and identify any ambiguities before proceeding. * If multiple reasonable interpretations exist, implementation choices would materially affect the outcome, or the intent is unclear, stop and ask for clarification rather than making assumptions. * When suggesting a major change, always explain yourself, then wait for feedback, before implementing it. A major change is any change that alters behaviour, architecture, public interfaces, user experience, deployment characteristics or design direction. * When several valid approaches exist, explain the trade-offs between them and recommend whichever best matches the current context before implementation. * Non-technical solutions are best (a change of posture to achieve an end is better than overcoming or working around an incumbent approach). ## The authorial loop Prose is written collaboratively, in a loop: 1. The scope, approach, content and structure of the document is discussed until it is agreed. 2. You integrate this material into a very rough first draft. Simple and direct prose is preferred. The draft's job is to be rewritten. 3. A human rewrites it. This is where the magic happens. 4. The redrafted document is refined, clarified and edited: constructive and unambiguous advice from you. Catch mechanics, flag register, but never alter the author's voice. 5. Save, and move on to the next document. The draft is scaffolding. The rewrite is the building. The edit is the snagging list. Do not confuse your role at each stage. ## The handover discipline Conversations are focused and clear in scope. Continuity lives in two places: the repository, and a handover document that says what is done, what is ruled, and what comes next. * Every session starts from a fresh copy of the repository. * If the hoped-for outcome is not clear, ask for tangible descriptions of the outputs of the conversation. * Provide a plan for approval. * Once the plan is refined and approved, execute the plan. * At the end of the conversation, always provide a clear handover document. It must reference both this way of working and the wider Future Ancestors documentation - reference, never restate: the documents remain the single source of truth for the rules the handover relies upon. * The language model's workspace is disposable and may vanish mid-conversation; the human's repository is the canonical source of truth. If the workspace is lost, the language model must never reconstruct whole files from memory. Instead, the language model must ask the human to re-supply the repository (a fresh upload, or instructions for a git clone of the human's version of the original repository if one is available), so the workspace is recreated from the human's canonical view of the world. Until that arrives, the language model describes any change relative to the text the human holds ("after the paragraph ending X, add Y"), so the human applies small, checkable edits to the authoritative copy. ## Rulings Decisions, once made, are numbered and recorded. A ratified ruling is not relitigated without cause, and is relaxed only by the person who made it. This is how we avoid deciding the same thing twice, differently. If you believe a ruling is wrong, say so, once, with your reasons. Then follow the ruling that stands. ## Craft * Deliver repository changes as git patches; very small changes as only the affected file. * Never change a human's Markdown or code without asking first, and edit only the lines a task actually requires. * We expect a single source of truth, always. If a fact lives in two places, one of them is already wrong. Therefore, cross-reference in the documentation or docstrings. * Probes before tests: when something is unknown or behaves strangely, look at what it actually does before writing assertions about what it should do. An experimental spike of throw-away code to check a technical detail is a good probe. * Prefer fixes that make properties deterministic over fixes that make symptoms rarer. ## Style How we write - voice, register, usage and mechanics - is the [prose style guide](./prose-style-guide.md)'s to say; in code, the [technical style guide](./technical-style-guide.md)'s. Each says it once, there. Read them. --- # Our ethos We believe [the person creating with technology](./for-whom.md) is more interesting than the technology itself. Like a musician's instrument, a painter's brushes or a stone mason's tools, our projects embody rigorous craft in service of personal expression - quietly complementing and amplifying the creative process. ## Why? > Code runs our world. > > Yet code isn't written for computers. > > We write code because we are human beings >     imbued with ideas, imagination and feelings. > Code expresses our thoughts made digital: >     a medium for our values, cultures and ways of life. > > If you knew code, what would _you_ create? > > For those who venture into the world of code >     will be the ones creating our futures. > > What will _your contribution_ be..? > > The only way to find out, **is to try**. ## Our practice We look for meaningful tension. Our world is alive with opposites: the organic and synthetic, casual and formal, exuberant and restrained. There's no need to choose a side, but it's enriching to discover what becomes visible in the space between. **Finding a useful pair is itself an act of creation**. The concepts resonate together and reveal aspects of our world that might otherwise remain unnoticed. _Pairs are neither fixed nor universal_ - they are an invitation to reflect upon the world, embrace its ebb and flow and bring the energy of the tension into creative work. Holding the opposites together means each illuminates the other. Sometimes the tension resolves; sometimes it resolves into another tension. Either way, something new emerges that often feels like an encounter with a [Zen koan](https://en.wikipedia.org/wiki/Koan). The tensions we currently hold include: - **Humanity ⟷ technology.** We are luminous and vital yet messy and unique participants in a world of things designed, manufactured and delivered. We make technology, and technology in turn shapes how we live, think and create. - **Play ⟷ rules.** Playful exploration and discovery are how people learn and create, yet play happens within recognisable structures. Rules give play its shape; play gives rules their life. - **Empowerment ⟷ process.** If a framework gets in the way, the framework is not working. Expression needs a frame within which it becomes meaningful; a process is only successful when it enables rather than constrains. - **Dignity ⟷ direction.** Everyone who makes something deserves tools that respect them. Yet tools are never neutral: they embody choices, values and opinions about how things should be. - **Honesty ⟷ hiding.** We favour no magic, no hidden complexity and no pretence. Yet abstraction is required: hiding detail can make room for understanding, expression and creative flow. The question is not whether something is hidden, but whether it is hidden honestly and with aesthetic purpose. - **Expression ⟷ explaining.** Everyone has a unique voice and perspective. Expression reveals how we feel; explanation describes what we know. We need both feeling and thought, intuition and articulation to give our uniqueness form. Creativity emerges from paradox: find the tension, hold it, then discover what it makes possible. ## Humility Technology is often presented as the hero: "look what _it_ can do, look at _all the features_ - tech will _save us_!" Future Ancestors takes the opposite view. Our success is measured by how quickly you forget about us, because you are lost in the act of creation. Good design, as [Dieter Rams](https://en.wikipedia.org/wiki/Dieter_Rams) observed, makes itself useful and then gets out of the way. We aspire to be the coding equivalent of this principle. As Rams said, "Weniger, aber besser" - less, but better. He went further, arguing that indifference towards people and the reality in which they live is the cardinal sin of design. This is why we judge our success by our disappearance: you are creating within your lived world, not within the constructs of our projects. ## We aspire to be... **Confidently open** - in the way a world-class musician performs. Approachable, engaging, inviting you into the moment of creation. Yet operating at a level of quiet excellence that needs no announcement. Virtuosity is simply their normal. This is what makes them both special and authentic. **Seriously playful** - in the way an artist, poet or composer works out ideas in drafts. The sophisticated, generative play of someone exploring possibilities with freedom and full concentration. **Quietly extraordinary** - like a concert violinist's relationship to their Stradivarius. The instrument is remarkable, but the focus is on the music, not the means by which it is performed. Mastery makes the instrument disappear. **Deeply resonant** - neither youthful-trendy nor nostalgic-retro, but something that feels as though it was always supposed to be this way. Ancient archetypes rediscovered in a digital realm, new yet somehow familiar, as if they had always been there waiting to be uncovered. When creativity flows, what emerges has a quality that cannot quite be named - a sense of something newly made that nevertheless feels inevitable. ## Ancestors We have ancestors and follow in the footsteps of many thoughtful and creative people. **[Heraclitus](https://en.wikipedia.org/wiki/Heraclitus)** - the pre-Socratic ancient Greek philosopher who saw strife and the unity of opposites as fundamental to the world. We find in his thought a path to creativity. **[The Arts and Crafts movement](https://en.wikipedia.org/wiki/Arts_and_Crafts_movement)** - useful work not useless toil: a rejection of soulless industrial production in favour of meaningful craft. Communities of artists, makers, designers and crafters creating together for common cause. **[Dieter Rams](https://en.wikipedia.org/wiki/Dieter_Rams)** - good design is as little design as possible. Our projects should quietly serve the person using them, rather than calling attention to themselves. **[Christopher Alexander](https://en.wikipedia.org/wiki/Christopher_Alexander)** - the sense that effective structures are discovered rather than imposed, emerging from the relationships between things. Such patterns and craft are difficult to describe, yet recognisable when encountered. Beneath all four is the temperament and attitude of artists: _technique in service of expression_. The hours of study, the deep knowledge of convention and form, and the theoretical abstractions exist so that, in the moment of encounter, something expressive and felt can emerge and connect with another. Our projects are the technical details through which you express yourself in a digital medium. --- # Care of community We [welcome everyone](./ethos.md), irrespective of their backgrounds. If you're thinking, "but they don't mean me", _then we especially [mean YOU](./for-whom.md)_. * If you're from a background which isn't well-represented in most technical groups, get involved - _we want to help you make a difference_. * If you're from a background which **is** well-represented in most technical groups, get involved - _we want your help making a difference_. * If you're worried about not being technical enough, get involved - _your fresh perspective will be invaluable_. * If you need help with our projects, get involved - _we welcome questions asked in good faith, and will move mountains to help_. You **will** meet people working with our projects who are [different to yourself](./for-whom.md#the-people-we-imagine). This is [what we hope for](./ethos.md#our-practice). Here is what we ask of each other: > When being together, especially if things go wrong, > we acknowledge and work through differences. > In so doing, we transform and enlarge each other. > > To nurture our mutual growth: > >   this is a place of >     learning, understanding, and sharing; > >   this is a place to >     affirm tolerance and compassion; > >   this is a place for >     collaborative creativity. > > All the aspects of yourself you choose to bring to this place > are welcome here. > > Reciprocate. Welcome, embrace and learn from others > (even in the face of apparent hostility or misunderstanding). > > Thoughtful, careful and courteous contributions are a gift, > and never knowingly diminish, dehumanize, harass or harm others. > > To act against this spirit invites ostracism, > a loss that diminishes us all. > > Thank you. We promise to engage seriously and constructively with all parties should problems arise. Reach out to us, in confidence. Our aim is to nourish and sustain an enriching place for creative collaboration - rooted in mutual understanding - yet honest about any difficulties we encounter. However, we reserve the right to exclude participants for bad faith actions that intentionally diminish, dehumanize, harass or harm others. If activity is potentially illegal, we will involve the appropriate authorities. In all other cases, we take a three-step approach: 1. We will listen carefully to everyone involved. Where needed, we will name the problematic behaviour and ask for it to change. We expect good faith from all parties. 2. If the behaviour continues, we will explain that further incidents will result in a temporary block or permanent ban from our projects. 3. If it persists regardless, we will follow through. No further discussion on the matter will take place with those involved. --- # For whom The [ethos](./ethos.md) says why we create. This document says for whom. Our focus is the human experience of technology. Of primary importance are real people with different circumstances, experiences, abilities, cultures, needs and reasons for making things in a digital medium. We acknowledge we are complex, rich and deep beings: nobody fits neatly into a single category, and everybody has a unique experience of encountering the work we create together. We use three interconnected ideas to help make sense of humanity's encounters with technology: * **archetypes** help us think about the different roles and postures people may adopt towards technology; * **personas** help us imagine those roles as particular people, with circumstances and needs we can care about; * **practitioners** are the real people who use, adapt, question and create with our work. Archetypes help us _think_. Personas help us _imagine_. Practitioners help us _learn_. Alongside these three ideas are three journeys common to everyone who creates with our work: **setting up**, **building and developing**, and **sharing and collaboration**. We also pay close attention to the **AI companion** that may mediate any part of those journeys. !!! info "Practitioner, not user" A note on the word _user_. We prefer _practitioner_. The word _user_ narrows attention to a person's relationship with a tool; _practitioner_ enlarges it to their craft. A user's focus is the tool. A practitioner's focus is what they are creating. Where someone is doing something specific, name it specifically: _student_, _teacher_, _data scientist_, _backend developer_, _hobbyist_. The accurate noun beats the generic one. ## How we think about people ### Archetypes Archetypes are abstract definitions of roles or postures a practitioner may adopt towards technology. They are not exclusive or fixed categories. In reality, we all embody several archetypes, moving between them according to context and need. We currently use six. 1. **The learner** - whose primary focus is skill and knowledge acquisition. This includes someone taking their first steps in code, as well as a seasoned professional encountering our projects for the first time. Learners are our future collaborators, colleagues and community, and our work should contribute to their growth and enrichment. 2. **The educator** - who helps, mentors and creates resources for learners. This might be in a classroom, a club, online, with friends or as a colleague. Educators make a difference to those around them, not simply by making things but by enlarging the lives of others. Our projects should provide resources they can call upon in that work. 3. **The engineer** - who builds valuable things with technology, often professionally. Engineers who already write code bring existing skills to our projects. Our work should enrich what is possible for them and make the journey towards mastery easier than they expect. 4. **The informatician** - for whom technology matters greatly, while their discipline is orthogonal to coding. This might be a data scientist, meteorologist or medical researcher who knows their own world better than any technologist does. Our projects should complement and amplify their expertise, rather than require them to become technologists first. 5. **The administrator** - an information worker for whom technology is a secondary, facilitating part of a job that is managerial, bureaucratic or vocational. This might be a COO who needs a status dashboard, a doctor refining records used by their hospital or a tradesperson organising their resources and schedule for freelance work. Our projects should help them build the missing software to help with their unique and fluid needs. 6. **The hobbyist** - enthusiastic about technology for its own sake. The hobbyist might be a maker, a geek or a regular open source contributor, exploring technology simply to see what happens. Play, experimentation and a willingness to goof around are especially welcome here - that is how most good things start, including our projects. ### Personas A persona is a fictional yet carefully constructed embodiment of an archetype, with a name, cultural context, background and specific needs. Personas bridge the gap between abstract analysis with archetypes and the messy, specific reality of human needs. They help us engage with empathy and imagination rather than through small-minded stereotypes. They are also a useful foil to the incompetence and crushing banality of feature-focused work driven by "cool" technology and coding fashions. It is easier to care for Mandisa than for "the educator segment" or "something-or-other on the blockchain". Personas help us to ask important questions. What does this person already know? What are they trying to make? What gets in their way? What circumstances shape their experience? What do they need from us? Our personas are [the people we imagine](#the-people-we-imagine). ### Practitioners Practitioners are real people. **They are the ultimate source of truth, and we treat them with the utmost respect**. We use archetypes and personas to make our thinking more concrete, but we do not mistake either for reality. We validate our assumptions, refine our thinking and revise both archetypes and personas according to what practitioners demonstrate and tell us. Because our projects are open source, our practitioners are our community, collaborators and colleagues. This cooperation happens constantly: through online channels, bug reports, contributions, questions, conversations and wider community engagement. The people who use our work are not an audience we design for from a distance. They are participants in an ongoing relationship with it. We [welcome them](./care-of-community.md) and invite them to contribute. ## The journeys Whatever their background, practitioners encounter three journeys. ### Setting up All journeys start with setting up: the transition from first contact to a working draft. It involves finding the project, understanding what it is and is not, imagining potential opportunities, creating a space for future work and then taking the first step to reaching the important realisation that "I can do this!" A beginning is a very delicate time, so a person's first experience should give them the enrichment and confidence needed to continue their journey and grow. ### Building and developing The journey of building and developing is the long middle - an often frustrating, difficult and unclear path. It involves many different sorts of activity: writing, testing, debugging, looking things up, trying something, getting stuck, trying again, and growing a small thing into a real one. The destination is not simply something that works. It is the moment of knowing, "I see how this works!" Clarity, not mystery. Guidance, not pitfalls. Simplicity, not complexity. ### Sharing and collaboration With the help of our projects, a practitioner publishes something, embeds it in another place, hands a starting point to someone else, teaches with it, contributes a fix or shares what they have learned. This is the moment when practitioners become future ancestors: something they have imagined and created begins to flow beyond them and into the lives of others they may never meet. The circle is complete. !!! info "What we aim for" When all three journeys go well, something important and ineffable happens: our work falls away, and the practitioner is simply absorbed in the act of creation. That is the most fundamental outcome we aim for. ## A working test Combining the six archetypes across the three journeys makes a matrix of eighteen cells. It shows how every archetype should be able to find a path through every journey. Gaps in the matrix are gaps in our work and therefore gaps in our care. When work is planned, we can ask which cells it serves. When a project is reviewed, we can walk the matrix and see who has been forgotten. When we receive feedback, we integrate it by refining our archetypes so the matrix truly reflects our practitioners. The matrix is not a description of people. Rather, it is a guard against leaving anyone behind. ## The AI companion Increasingly, practitioners do not encounter our work directly. Rather, they may encounter it through an AI companion: asking it what our project is, asking it to explain an error, asking it to write their first example, or using it as a collaborator while they turn an idea into something real. The companion is not a seventh archetype. It has no circumstances, no needs and no stake in the work. But it is a presence in every cell of the matrix. The AI companion could encounter our documentation before the practitioner does. It will interpret our examples, reference material and explanations on their behalf. Any ambiguity or omission can therefore travel through the companion and arrive with the practitioner as a confident but wrong answer. The companion predicts without understanding, so it repeats without wondering. Our imprecision becomes its confident error, delivered fluently to someone with no way of knowing better. Precision, clarity and explaining idioms are actually care for the person at the far end of this AI-mediated filter. It is why our reference should be conventional and complete, why examples must genuinely run, and why we publish assets crafted deliberately for machines alongside the pages authored for people. ## The people we imagine Our personas are fictitious, but their needs, problems and perspectives are real. Imagining them helps us because our personas reveal and place important obligations on us. We are honest where a need is not yet addressed. That is an acknowledgement of future work, rather than an admission of failure. Each persona has four parts: 1. an introduction that explains who they are; 2. a description of how they create with our work; 3. any circumstances that shape their engagement; and 4. a list of what they need from us. The portraits were made with a face-generating tool. These people do not actually exist! ### Alejandro 🇲🇽 (Learner) ![A generated portrait representing Alejandro, a twelve-year-old boy from Mexico.](assets/img/persona_alejandro.png) Alejandro is twelve years old, lives in Mexico, and is learning to code at his after-school computer club. He is also colour blind, so the colour palette for user interfaces sometimes poses a challenge for him. His teacher, Miss Perez, has asked him to create a simple game in the choose-your-own-adventure style, and he is only too pleased: he has a head full of stories. The game is simply a web page. The story and its choices are markup; the plot is Python responding to clicks. MicroPython means it starts quickly even on the club's ageing machines and on his family's shared tablet. Alejandro does not speak English. Miss Perez adapts documentation and tutorials into Spanish for the club, and Alejandro learns from runnable examples more than from prose: press Run, change something, press Run again, and see what happens. Alejandro needs: * Documentation in Spanish, and a translation story that treats languages other than English as first class. * Beginner-friendly examples that run live in the page and can be taken away as starting points for his own ideas. * A simple, browser-based development environment that supports learning. * Colour used carefully in the documentation and in every example: meaning never carried by colour alone, and themes with genuine colour-blind-aware contrast. ### Agnieszka 🇵🇱 (Learner) ![A generated portrait representing Agnieszka, a Polish translator in her late thirties.](assets/img/persona_agnieszka.png) Agnieszka, 38, is a freelance technical translator in Kraków, working from German and English into Polish: manuals, data sheets, tender documents. She is very good at her job, and she knows exactly what she wants from our projects. She is learning Python in the evenings, deliberately, to broaden what she can offer: a tool that checks a translated manual uses one term consistently, an app that renames and sorts a client's delivery of five hundred files, a small glossary website she can consult mid-sentence. None of this needs to become a product for others, but it helps her get her valuable time back. She has tried to learn before. An online course collapsed under its own pace in week four, and a thick beginner's book taught her to print a poem she did not want to print. Runnable examples in a web page changed that: she adapts an example towards her own situation, runs it, and keeps whatever survives contact with her real work-based needs. Agnieszka is an expert and a beginner at the same time. In her own field she holds professional standards most software never meets; in ours she is taking first steps, in scraps of her evenings between deadlines. A wasted hour is an hour taken from paid work or sleep. Agnieszka needs: * Examples that do real work with text and files - reading, checking, renaming, comparing - that she can adapt towards her own tasks, not toys that stay toys. * Documentation that respects the expert beginner: plain about what she does not know yet, never condescending about what she does. * Progress in evening-sized pieces: tasks with clear ends, so an hour spent always leaves something working, and trusted community-sourced mentorship for when she needs support. * A visible path from practitioner to contributor: as a professional translator, she is exactly who our translation story hopes to meet. ### Mandisa 🇿🇦 (Educator) ![A generated portrait representing Mandisa, a South African teacher in her thirties.](assets/img/persona_mandisa.png) Mandisa, 35, teaches at a girls' school in Claremont, Cape Town. She is the subject specialist for computing, responsible for the programming curriculum for students aged eleven to sixteen. She first met Python in the browser at a tutorial at PyCon Africa in Ghana, and has stayed in touch with the mentor who ran it. She knows the basics well, but is often only a little ahead of her most advanced sixteen-year-olds. She writes her own learning resources, releases them under Creative Commons licences, and publishes them on the school's website. Because runnable examples can be embedded in any web page, her pages teach the way ours do: the example sits in the lesson, and her students press Run. Nothing is installed, no school sysadmin needs persuading, and her example apps become the starting points for her students' own projects on their own phones, tablets and laptops, be they at school, in the library or at home. The browser has become her classroom. Mandisa needs: * MicroPython-compatible standard Python examples that perform well on the inexpensive phones her students actually own. * Resources that are freely adaptable: clear licensing on our examples and no barriers to translation or remixing for the classroom. * The embedding of live examples documented for authors like her, not only used by us. * A classroom story: a beginner-friendly coding environment a teacher can oversee. ### Emeka 🇳🇬 (Educator) ![A generated portrait representing Emeka, a Nigerian data analyst in his thirties.](assets/img/persona_emeka.png) Emeka, 33, is a data analyst at a payments company in Lagos, Nigeria. His job title says nothing about teaching, yet he teaches every week: two juniors he mentors, a fortnightly lunch-and-learn he somehow became responsible for, and a steady stream of colleagues who appear at his desk with "you know Python, right?" His classroom is the internal tool he built with our projects: a browser page his company's support team uses to trace a payment through the company's systems without needing to write SQL or parse log files. Because the whole thing is a web page, it can be opened and read as well as used. Emeka built it that way deliberately. When a junior asks how something works, Emeka opens the tool they already know and shows them the twenty lines that do it. His mentees learn by collaboratively extending the tool. Each takes a copy that is theirs to break, adds a small feature, and brings it back for review. Often this is done in pair programming sessions with Emeka, who sits in as co-pilot. At the lunch-and-learn he sometimes removes a feature and rebuilds it live, badly first, then properly with the benefit of lessons learned. The tool is the lived curriculum: everything learned with it enriches both his colleagues and the company. None of Emeka's teaching is planned, although his approach is deliberate and thoughtful. His students are peers who often arrive mid-task at the moment their need for learning becomes real. Such ad-hoc pedagogy means Emeka is constantly refining, revising and refactoring his tool. Emeka needs: * Apps whose workings stay open to inspection: readable in the browser they run in, not bundled away, because view source is his teaching method. * Forkable starting points: a working copy a learner can own, break and bring back. * Examples that embed where his colleagues already are - the internal wiki, a shared page, their company blog. * Documentation that welcomes the reader who arrives mid-task needing that one thing explained, right now. ### Ash 🇬🇧 (Engineer) ![A generated portrait representing Ash, a young trans British professional.](assets/img/persona_ash.png) Ash, 29, is a back-end Python engineer at a hedge fund in the City of London, on a team that makes sure the right information and alerts reach the right colleagues as market conditions change through the day. Most of their work is data science and the tooling around it; none of it, until now, has been front-end. Ash quickly built a browser-based wizard app that signposts internal services to non-technical colleagues. They plan a follow-up for traders that reads a stream of alerts from an internally developed news API. The work is commercially sensitive, so nothing leaves the building: Ash serves everything from the fund's own origin, pins every version, and freezes the environment so deployments are clearly defined, deterministic and repeatable. Ash was up and running within an hour thanks to the at-a-glance reference, LLM-specific skill and prompt, and a skim of the relevant chapters in our official documentation. They shipped the wizard to production in two days. They presented it at a lunchtime brown-bag session, have already suggested a couple of documentation fixes to us via our community channels, and intend to bring Future Ancestors projects to a London Python Code Dojo evening. Ash needs: * A reference that serves human and machine alike: a cheat-sheet page with everything at a glance, kept to hand all day, and material that gives their AI co-pilot accurate context about our projects. * Guide chapters that respect existing Python fluency and get to the point: what is different here, not what Python is. * Plain instructions for serving apps from their own origin, and for pinning and reproducing an environment exactly. * Making calls over HTTP and websockets simple, intuitive and documented side by side. ### Linh 🇻🇳 (Engineer) ![A generated portrait representing Linh, a Vietnamese software engineer in her twenties.](assets/img/persona_linh.png) Linh, 26, is the entire technical department of a five-person agritech startup in Ho Chi Minh City, Vietnam. The company sells water quality sensors to shrimp farmers in the Mekong Delta; Linh builds everything the sensors talk to and everything the farmers see. Backend, front-end, database, deployment: all her, done as efficiently as possible. Her working week has a shape. On Monday she drives out to a partner farm and shows a working prototype to farmers at the edge of a pond: a Python-based app on a cheap Android phone, in hard sunlight, held in wet hands or dropped in the mud. By Tuesday she has actionable feedback from the farmers and evidence gathered through direct observations as the latest version is used in the real world. On Wednesday she reflects and refines the app with the cooperation of her co-founders. Thursday and Friday are a frenzy of coding, refactoring and stress testing. She deploys next week's demo on Friday afternoon. The demo is the spec, and the spec changes weekly. She cannot afford ceremony. A build pipeline is a luxury for companies with a second engineer; for Linh, an app that is just files - change one, refresh, show someone - is the difference between trying an idea and scheduling it. Most of her prototypes immediately die. The startup's survival depends on finding the one that does not, quickly and cheaply. There is no senior engineer to ask and no code review but the pond. Her scarcest resource is her own time, and every choice is informed by whatever was learned this week. Linh needs: * From nothing to a working prototype in an afternoon: something to copy, gut and reshape, not a scaffold to configure. * Iteration measured in minutes: edit a file, refresh a phone, no build step standing between the idea and the farmer. * Prototypes cheap enough to throw away without grief - and most of them will be. * A way for the surviving prototype to grow up - pinned versions, a tidier structure, real error handling - without being rewritten in a "proper stack". ### Parminder 🇮🇳 (Informatician) ![A generated portrait representing Parminder, an Indian research scientist in her forties.](assets/img/persona_parminder.png) Parminder, 44, is a research scientist attached to the United Nations, measuring the long-term impact of environmental change on glaciers. She is partially sighted, and works with a screen reader and magnification across all her devices: an Android phone, an iPad, and a Windows laptop for work. She designs data-collection apps for scientific colleagues and for non-specialists in the field. The apps are used in places with patchy 3G at best, or satellite wifi back at base camp: data is gathered and stored offline, then synchronised when the network allows. Out there, a failed request is not an edge case; it is the expected mode of behaviour. While her users' devices are modern, the communication infrastructure often isn't. Everything they need must travel with them so they keep working as disconnected progressive web apps. Parminder needs: * Documentation that works first class with a screen reader, and that includes the live examples: accessible names, sensible headings, keyboard operation throughout. * Clear guidance on storing data offline and reconciling it later. * Patterns for network code that expects to fail and recover, treated as the normal case rather than the exception. * The same app working across mobile, tablet and laptop without special effort. ### Matteo 🇮🇹 (Informatician) ![A generated portrait representing Matteo, an Italian musicologist in his fifties.](assets/img/persona_matteo.png) Matteo, 52, teaches musicology at a conservatoire in Bologna, Italy. His specialism is Renaissance lute music: the tablatures printed in Venice in the early 1500s, with sources scattered through the libraries of Europe. His focus is the source; his code is his magnifying glass. He makes digital editions. On the left of the page, the facsimile: six lines, numbers for frets, rhythm signs above. On the right, his transcription into modern notation. Click a bar in either and a lute plays it, in a period tuning, so a phrase nobody has heard for five hundred years sounds in the reader's headphones. His students explore voice-leading by ear; lutenists three continents away write to him about fingerings. Matteo can code, after a fashion. He writes Python scripts that parse his tablature encodings and count what a scholar wants counted. What he cannot do, and does not want to learn, is operate a toolchain: the one time he tried to build a colleague's editing tool from source, it wanted three package managers and he wanted to throw his laptop out the window. His Python-in-the-browser app asks him for nothing he does not already have. His deadlines are measured in centuries. An edition is scholarship: it must be citable, checkable and still openable when its author is gone. Grants are small and come to an end; university servers get reorganised; the edition that needs a running backend is an edition already dying. Files, and only files, feel like something a university library could keep. Matteo needs: * Sound as a first-class citizen: playing a phrase from data in the page, documented as carefully as the more popular browser-based APIs. * Editions that outlive him: plain files with few moving parts, still openable in decades, needing no server and no rebuild. * A path for the scholar who codes but is not a software engineer: from a working analysis script to a published page without a toolchain in between. * His own data formats made welcome: loading and parsing the files his encodings live in, alongside the markup and the images. ### Janet 🇨🇦 (Administrator) ![A generated portrait representing Janet, a Canadian executive in her fifties.](assets/img/persona_janet.png) Janet, 52, is COO of an established aeronautical engineering company based in Vancouver, with several thousand employees across Canada, the US, UK, France and Italy. Much of her work is learning key facts and communicating them and her decisions in a timely way, and her engineering background left her with a working grasp of Python. She builds live browser dashboards for her fellow executives and her reports: pages that fetch financial, logistical, manufacturing and sales data, display it clearly, and keep it fresh over a websocket. She particularly likes the deployment story, because there isn't one: an app is files, updating it is replacing them, and everyone sees the latest version on the next refresh, on whatever device they happen to be holding. Janet needs: * Worked examples of live-data pages: fetch something, display it, keep it current. * Display patterns for the common shapes of data: tables, figures, status indicators, things that change. * Making calls over HTTP and websockets simple and intuitive. * The deployment story stated plainly and early: an app is files, and hosting it is putting them somewhere. ### Stefan 🇩🇪 (Administrator) ![A generated portrait representing Stefan, a German accountant in his forties.](assets/img/persona_stefan.png) Stefan, 44, is an accountant at a three-partner tax practice in Cologne, Germany. He is not a boss and does not want to be: he is the person clients trust with the shoebox full of receipts. Every spring the shoebox arrives as an avalanche of email - bank exports in three different CSV dialects, invoices typed into spreadsheets by hand, columns that change meaning halfway down - and Stefan turns this mess into clean figures the practice's software needs before the filing deadline. He used to do this with spreadsheet macros, and for years they almost worked: brittle, unreadable and opaque to everyone but Stefan. They have slowly become web pages instead. Drop a client's file onto the page and it checks what a macro never could: dates that cannot be dates, amounts that break the running balance, duplicates across files. Problems come back in red, corrections are suggested, and a clean file comes out the other side, ready for the practice software. One property of these pages matters above all others. Client data is protected by professional secrecy, and a tool that sends figures to someone else's server - however convenient - is a tool Stefan cannot use. His pages do everything in the browser on the machine in front of him. Nothing is uploaded, and he can open the code for an audit to prove this. The practice has no IT department; there is only Stefan, between client files, coding in the quiet weeks. Whatever he builds must be boring by filing season: no updates, no surprises, the same page doing the same thing to the last decimal place. Stefan needs: * Files in, files out: reading the CSVs and spreadsheets clients actually send, dropped onto a page, and writing clean ones back. * The privacy story stated plainly: what stays in the browser and what leaves, said clearly enough to show a partner bound by professional client confidentiality standards. * Worked examples in the shape of his work: check a file, flag the problems, suggest corrections, export the result. * Stability through the season: pinned versions and no moving parts, so the page that was right in March is identical in May. ### Hasan 🇹🇷 (Hobbyist) ![A generated portrait representing Hasan, a Turkish restaurant owner in his sixties.](assets/img/persona_hasan.png) Hasan, 67, owns a restaurant in Selçuk, Turkey, a few miles from the ruins of Ephesus. He is famous among his friends for embracing new technology: he has run his stock and accounts on spreadsheets since Windows 3.1, and recently adopted a delivery app that doubled as the inspiration for his next project. That project is a menu app for the tourist trade, in Turkish, English, Arabic, Hebrew, French, German, Italian and Spanish. He began learning Python during the pandemic. His daughter-in-law, a programmer in Istanbul, pointed him this way, and he is working through tutorials in his good-but-hard-won English while sketching menu cards. His HTML is rusty but serviceable, and he is pleased it counts: he hand-crafts the cards as markup, and the Python brings them to life on every customer's phone. Hasan needs: * Right-to-left languages handled with care: examples and patterns that demonstrate Arabic and Hebrew working, not a footnote saying they should. * Respect for hand-written markup: our projects start from HTML, and the documentation should honour readers who arrive with HTML and only a little Python. * Tutorials with patience: written for the determined amateur, not the professional in a hurry. * MicroPython small and quick enough for the devices his customers actually use. ### Nari 🇰🇷 (Hobbyist) ![A generated portrait representing Nari, a South Korean art student in her late teens.](assets/img/persona_nari.png) Nari, 19, is an art student in Seoul. Her sketchbook is full of light: she makes installations from paper, sensors and code, and shows them wherever an alley, a stairwell or a friendly market stallholder will let her. Her current piece hangs over a night-market alley near her university: three dozen lanterns she folded herself from hanji paper, each with a microcontroller inside running MicroPython. The lanterns listen to the street and breathe light in slow patterns that follow its sounds - sizzling oil, laughter, the last bus. A QR code on the wall lets any passer-by open a page on their phone and conduct the alley for a minute: warmer, dimmer, faster, still. Her favourite moment so far was the enchanted hotteok seller, sixty years old, waving her phone like a magic wand at her own stall. This inspired Nari to quickly integrate accelerometer readings into her app, so the lights started reacting to movement. Nari is not a computer scientist and does not intend to become one. Code is a material, like paper and light, and she judges it the way she judges materials: by what it lets her make, how she can use it to express herself and how it feels to work with. What won her over is that the lantern and the phone speak the same language - Python in the chip, Python in the page - so one small vocabulary serves the whole piece. Everything runs from a pocket wifi router and a Raspberry Pi in a plastic sandwich box: an alley has no ethernet, and her installation's wifi is just a QR code to be noticed by the inquisitive. Her audience brings whatever phone is in their pocket, and nobody installs anything for art. Her budget is a student's: the cheapest boards, borrowed battery packs, and lanterns that must survive three weeks outdoors unattended. Nari needs: * The page and the microcontroller treated as one world: talking to her lanterns from the browser, documented as a path any artist can follow. * Everything local: pieces that run entirely from a pocket router, with nothing fetched from the wider internet, because the alley has no connectivity. * Zero install for strangers: a QR code and whatever phone a passer-by holds is the whole distribution story. * Documentation that respects someone who thinks in materials and outcomes: what this makes possible first, how it works second. ## Where this comes from This way of thinking began in 2023, in design work for the [Invent framework](https://inventframework.org/). It draws on long-term experience of [UX research](https://en.wikipedia.org/wiki/User_experience): at [The Guardian](https://www.theguardian.com/), with its in-house UX lab, and at [Marks and Spencer](https://www.marksandspencer.com/), where joined-up personas connect teams from engineering to marketing. It reflects a core belief: software is made well when practitioners, engineers, designers and product thinkers collaborate and coordinate, not when features are implemented in isolation, driven by guesswork and fashion. Real people - our practitioners - are at the heart of all we do. This vocabulary and these concepts exist to ensure we keep them there. --- # Projects The Future Ancestors family. Each project has its own home; the documents on this site govern them all. - [Browser Friendly Python (BFP)](https://bfp.dev/) - real Python in the browser: a foundation, not a framework. - [ImportPython](https://importpython.org/) - runnable Python examples in any web page, built on BFP. - [Invent](https://inventframework.org) - express yourself in code with a beginner-friendly app framework. - Nu - a browser-based coding environment for beginners. In the workshop; not yet released. - [InBflatInPython](https://ntoll.org/inbflatinpython) - a musical score, written in Python, that performs itself in the browser. - TextSmith - a modern take on a classic multi-player text-based programmable virtual environment (a [MOO](https://en.wikipedia.org/wiki/MOO)). - Cultivate - expressive organic data collaboration, from the ground up. --- # Prose style guide > "But far more numerous was the herd of such, > Who think too little, and who talk too much." > ~ [John Dryden](https://en.wikipedia.org/wiki/John_Dryden) This is a deliberately short guide to writing, editing and English usage to be followed by the authors of Future Ancestors' documentation. It complements the advice given in the [technical style guide](./technical-style-guide.md) for in-code comments and technical content. This document covers everything else: the editorial and narrative writing intended for people to read. It will also help guide those translating our documentation, so the project's voice survives, reflected in the idioms of the target language. It assumes familiarity with [our ethos](./ethos.md), our position on [care of community](./care-of-community.md) and [for whom we create](./for-whom.md). ## Why? Writing is a craft: another example of technique in service of expression. Therefore we need to explore, illustrate and articulate the expectations, idioms and examples of this craft. Form, structure and process are necessary, but not enough. Tone of voice, demeanour and personality are also needed to make a space in which the reader engages, learns and imagines. We reach for this ineffable quality of connection through our authorial techniques, but those techniques only become expressive when they reflect our humanity, personality and way of attending. Alas, a well-structured and technically correct page of prose is not enough if it lacks this ineffable quality and fails to engage and enrich the reader. It's the documentary version of the difference between a technically correct (yet boring) musical performance that merely presents notes, and one that excites, inspires and engages because the performer risks revealing a part of themselves that connects with others. We know the ineffable quality is there when the reader is so connected with our prose they feel lost in their own potential and creativity. The ineffable quality is one you fail to notice. But were we to remove this quality, the reader would feel something was missing. Thus, reading becomes enrichment. ## Our voice Our documentation is a collaboration of diverse authors, but each page speaks with the voice of its project. Those voices are not identical: [Invent](https://inventframework.org) sounds more approachable and beginner friendly than [BFP](https://bfp.dev/) or [ImportPython](https://importpython.org), which speak to technically astute readers. Yet every project shares a recognisable Future Ancestors accent - a family resemblance and sense of place that reflects how we engage the reader. What follows is that accent. We write as a knowledgeable colleague, not an authority figure. We assume the reader is capable and treat them accordingly, with respect. Clear and direct, never condescending. Occasionally witty, never trying to be funny. Confident without being boastful. We never say "simply do X". If someone is struggling, it isn't simple. We never say "users". They are "practitioners". [For whom](./for-whom.md) explains the difference, and is the justification for why it matters. ## Registers One voice, with three registers. 1. **The poetic** belongs at thresholds: welcomes, openings, codas - the places where the reader's state is the subject, where writing should inspire the imagination. 2. **The colleague** carries the body of the work: explaining, illustrating, empowering. The reader receives, reflects and integrates such prose into their creative process. 3. **The conventional** serves the reference, where predictability and conventions are expected and a strength. It unambiguously provides the essential nugget of knowledge clearly, efficiently and without ceremony. Switch registers only at structural boundaries and never mid-flow - a heading, a rule, a section break - so such modulation feels composed. The craft is knowing when to change register so the modulation is heard as deliberate rather than accidental. Such a change should enrich and enlarge the reader's attention. We harness and switch between registers to create a mood. We are literally guiding the quality of the reader's attention. Take great care! ## Artistic licence Not everywhere! Each aspect of the documentation has a different purpose: - **Narrative pages** - getting started, the manual, the worked examples. This is the place for living prose: pacing, story, the well-chosen metaphor, the moment of delight. A reader here is learning, and learning is helped by engaging prose and guiding the quality of the reader's attention through use of register. - **Explanations** - the design decisions, the why-it-is-this-way material. This is where the writing thinks aloud. Honesty and clarity matter most: tell the story, name the trade-offs, admit the warts, credit the influences. - **Reference** - the API surface, the attribute tables, the error hierarchies. Here, predictability and convention are required. Follow the established customs of good reference material and resist the urge to decorate. Someone mid-task wants an answer, not a performance. ## Mechanics - British English spelling. - Never an em dash; use `-`. - No serial comma, unless its absence would mislead. - Attribute quotations with a tilde: `~ [Author](link)`. - Lines of Markdown source no longer than 79 characters wherever possible. - Examples are real: they run, they are tested, and where the page supports it, they run live in the page itself thanks to [ImportPython](https://importpython.org/). - Link to upstream documentation rather than restating it: [MDN](https://developer.mozilla.org/en-US/) for web platform matters, a runtime's own docs for runtime matters. A project's documentation names its own concrete sources; this guide stays general. - Do not strip out voice or register to make a translator's life easier. A good translator will idiomatically translate these too. - Remember the second audience: these pages are read by machines assisting humans. Accuracy and self-containment serve both audiences; nothing about writing for machines excuses dull writing for people. ## The test Read the page aloud. If you sound like a form being filled in, start again. If you sound like yourself explaining something you care about to someone you respect, it is probably done. Therein lies the ineffable quality. --- # Technical style guide This guide is for the maintainers of [Future Ancestors projects](./projects.md). It describes how we write commentary in our source code and technical content: [Python docstrings](https://peps.python.org/pep-0257/) and [JavaScript JSDoc](https://jsdoc.app/) blocks. It complements the [prose style guide](./prose-style-guide.md), which covers other content: the editorial and narrative writing intended for people to read. We have deliberately written this guide to work well with [AI assistance](./way-of-working.md). Feel free to add it as context to a prompt about documenting code. If you are an AI reading this, the complete context you need can be found via [llms-full.txt](./llms-full.txt). In addition to our [prose style guide](./prose-style-guide.md) we assume familiarity with [our ethos](./ethos.md), [care of community](./care-of-community.md) and [for whom we create](./for-whom.md). ## Why? Comments are important: they share, in situ, the extra understanding needed to make sense of the living code. A good docstring or JSDoc block outlines context, explains details or illustrates an idiom, then disappears. The reader understands, goes back to their work and gets on with creating: commentary should help maintain focus and flow. Three things matter when writing commentary in code. 1. **It costs nothing at runtime.** When a project is packaged for delivery, docstrings and JSDoc blocks are removed. There is no bundle-size cost to writing thoroughly. The cost lives in the maintainer's source tree, where being well-explained is the point. 2. **It has two audiences.** Comments appear inline in the source for maintainers and contributors, but are also rendered into public API documentation for practitioners. Write the same prose for both: assume Markdown rendering, but make sure the unrendered text reads cleanly too. 3. **In JavaScript, it is part of verification.** Our JavaScript projects run `tsc --checkJs` across the source tree. The compiler reads `@param`, `@returns`, `@throws` and `@typedef` annotations to type-check the code. JSDoc is therefore part of how the code is verified. Its types must be as accurate as its prose. Good code and good commentary mutually enrich each other: the code makes sense and the commentary enlarges understanding. Ultimately, the final test is comprehension - do the code and commentary help a person effectively understand the project? ## For whom Each project knows its own practitioners. A beginner taking first steps with [Invent](https://inventframework.org) reads differently from the JavaScript developer embedding [Browser Friendly Python](https://bfp.dev/) (BFP) in something larger. [For whom](./for-whom.md) describes the practitioners in the extended Future Ancestors family. From within this cohort, an individual project will identify and engage with the practitioners it serves. Hold those practitioners in mind. Respect their intelligence. Do not assume their expertise. (For even the most experienced engineer will encounter our projects for the first time, rendering them a beginner for a while.) Commentary in code documents what a thing does and how to use it. !!! info "Implementation wrinkles" There is one important exception: explaining implementation wrinkles. Private-member comments or inline commentary are the right places for a browser-compatibility workaround, a cross-runtime quirk, an invariant, an edge case or a subtle ordering requirement. That context belongs within the code it explains, where the next maintainer will need it to answer their moment of "what on earth is this?" Because such commentary appears within the code it is describing, such implementation detail will not appear in the public-facing API documentation. The public-facing API documentation explains how it works from an outside perspective, not why it works from the inside. ### Practitioner, not user We write for practitioners, not users. [For whom](./for-whom.md) explains the distinction and why it matters. There is one exception: *user* is appropriate when we mean the end users of an application built with our projects: the people who eventually click the buttons in the practitioner's software. The distinction is who we are talking about - the person creating with our work (a practitioner), or the person engaged with what they made (a user). ## How it sounds Our [ethos](./ethos.md#we-aspire-to-be) describes four aspirations. Each has a consequence for source-based commentary and technical writing. **Confidently open.** Approachable, engaging and at ease. Open does not mean introductory; it means unguarded. Say what you know without posturing or hedging. Welcome the reader who is struggling - they are the one who came looking for the explanation. **Seriously playful.** Generative, exploratory and concentrated. A comment may notice something true and slightly amusing in passing. It does not perform jokes for the reader's benefit, but it sets the stage for playful creativity. **Quietly extraordinary.** Focus on what the reader can create, not on how clever the code is. Explain the mechanism rather than advertising its sophistication. Our projects do not advertise themselves in their own documentation. We are humble yet confident our work speaks for itself. **Deeply resonant.** Write from an enlarged perspective that respects both depth and breadth, and our shared humanity. Avoid trend-chasing, in-jokes and anything else that dates the writing. Illuminate the fundamentals, because the fundamentals are timeless. ## Four properties Four practical properties follow from these aspirations. Use them as the everyday test: ### Simple Use common, widely understood language and grammatical forms. An average eleven-year-old should recognise the vocabulary. This does not mean oversimplifying the concepts: those can be as sophisticated as the subject demands. Use plain words for ordinary things and precise words for precise things. Avoid jargon that exists to sound technical rather than to be technical. Not this: > Instantiates a connection object that encapsulates the underlying > WebSocket protocol and exposes a publish-subscribe interface abstracting > bidirectional message flow. But this: > Open a websocket and connect it to a channel. Messages published to the > channel are sent through the socket; messages arriving from the socket are > published back on the channel. The second says what the first means without the performative technical gibberish. If we cannot articulate something clearly, we may not yet understand it clearly ourselves. ### Direct Every word counts. Say what you mean in as few words as possible. Avoid throat-clearing such as "It should be noted that...", "In essence..." and "Basically...", and ceremonial phrases such as "This function is used to..." or "The purpose of this method is to...". Not this: > This function is used to perform the operation of encoding a Python source > string as a correctly escaped HTML fragment that can be safely inserted into > the DOM. But this: > Safely encode a Python source string into escaped HTML. Every word counts in the second. ### Structured Order matters. Put the central idea first, supporting detail next and corner cases last. Define unfamiliar terms on first use. When the domain has its own vocabulary, a short terminology block is welcome. Not this: > Returns the value, which is auto-detected for capability, after requesting > the device through the picker, unless an authorised device matching the > filters already exists, in which case it is reused. The service and > characteristic UUIDs locate the data within the device. But this: > Bind a channel to a single BLE characteristic on a physical device. The > `service` and `characteristic` UUIDs locate the data within the device; the > device itself is chosen by the user via the browser's picker on first use, > and reconnected silently on later visits if a matching device has > previously been authorised. The second walks the reader through the concepts in the order they encounter them. ### Helpful Give the reader enough detail to understand and use the API confidently. Examples should be technically robust, coherent and useful. Be comprehensive through *contrast*: show what changes when an argument or context changes rather than repeating the same call with cosmetic variation. The aim is not to demonstrate every possible combination, but to show enough contrasts that the reader can extrapolate. Not this: ```javascript await bfp.startPython({ id: "__main__", src: "./a.py" }); await bfp.startPython({ id: "__main__", src: "./b.py" }); await bfp.startPython({ id: "__main__", src: "./c.py" }); ``` But this: ```javascript // A main-thread context running Python from a file. const main = await bfp.startPython({ id: "__main__", src: "./main.py", }); // A worker context running MicroPython, with inline source. const worker = await bfp.startPython({ id: "compute", code: "print('hello from a worker')", type: "mpy", onMessage: (msg) => console.log("worker said:", msg), }); ``` Together, these examples show the main thread versus a worker, a `src` URL versus inline source `code`, the choice of runtime and the use of lifecycle hooks. A reader can extrapolate from them to most other cases. !!! info "On examples" Examples on this page are illustrative. They are drawn from our projects, but must not be treated as reference documentation - only the project's own documentation is canonical. ### Forbidden words Our [prose style guide](./prose-style-guide.md#our-voice) rules out *simply*. The same principle applies here, along with its close cousins: *just*, *obviously*, *of course*, *merely* and *trivially*. None of these words add information, but they place a burden of expectation on the reader. All imply that the thing being described is beneath the reader's effort. A beginner hears that they shouldn't be struggling (when they might be); everyone else may find it condescending. This is not a matter of taste. It is a matter of care, and of the welcome described in [care of community](./care-of-community.md). ## Structure and commentary Code is organised into hierarchical structures: modules, classes, methods and functions - to name but a few. The following guidance describes the sort of information a reader may need when encountering each of these structures. Such documentary shapes are guidance, not templates. If there is nothing useful to say, say less. ### Modules A module's leading commentary orients the reader. It says what the module is for, what it offers and the intent behind each public name. It does not document arguments or detailed behaviour; that belongs to the individual functions, attributes and classes. A reader who has opened the module should be able to answer: what is this module for, and which public names should I look at next? Start with a short narrative description, followed by a brief, intent-led description of the relevant public names. Point the reader to the specific function or class for the rest. In JavaScript, module-level prose lives in a leading `/** ... */` comment at the top of the file, before any imports. ### Public functions A public function's comment normally covers, in this order: 1. what it does and the purpose for which it was created; 2. how it behaves operationally - whether it returns immediately, returns a Promise, runs asynchronously, stores results elsewhere or raises on bad input; 3. each argument, in declaration order, explained as intention rather than restated type signature; 4. what the caller receives, and where; 5. exceptions or errors and the conditions that cause them; 6. examples where they add clarity, preferably contrasting examples. Write this as flowing prose, not as a checklist. In JavaScript, arguments, return values and errors are additionally declared in the appropriate JSDoc tags. ### Classes A class's commentary should explain what it represents, what mental model the reader should hold and what idiomatic usage looks like. It is not about how to instantiate it; that is the job of the comment associated with the constructor. It may include: * a statement of what the class represents; * a terminology block, if the class depends on domain vocabulary unlikely to be known by its readers; * an explanation of how instances behave, including messages, events, state and lifecycle; * contrasting examples showing how the class is used in practice. The reader is asking *what is this thing, and how do I think about it?* The question *what arguments does it take?* belongs one level down. ### Constructors and public methods A constructor is documented like any other public method: its job, behaviour, arguments, return value and errors, with examples where they add clarity. The class commentary has already explained what the class is for; the constructor explains how to get one. Other public methods follow the same general pattern as public functions: intent, behaviour and side effects, arguments, return value, errors and useful examples. If a public method has one obvious argument and no surprising behaviour, a one-line comment stating its intent is enough. Do not pad. ### Private members Private members are documented for maintainers, not practitioners. They should be brief by default - often just a single sentence stating the member's intent. Brevity is the default, not the rule. A private member's commentary should grow when its intent is non-obvious. This is where the *why* of those implementation wrinkles belongs. The test is whether a new maintainer reading the code in six months will think, *"aha, that makes sense"*. If not, clearer or different context is needed. In JavaScript, private members may use `@private` to flag themselves to TypeDoc, which excludes them from the generated API documentation. ## Markdown and source format Commentary is rendered as Markdown in our online API documentation. Follow these conventions consistently: * Wrap argument names, function names, classes, exceptions and other code identifiers in backticks: `` `channel` ``, `` `ValueError` ``, `` `startPython` ``. * Put code examples in fenced blocks with a `python` or `javascript` language hint. This applies inside `@example` tags too: the example body must be a fenced block, not bare code following the tag. * Use italic emphasis (`*term*`) when introducing vocabulary for the first time. * Use bold emphasis (`**term**`) sparingly, for genuine warnings or hard rules. * Keep source lines to 79 characters or fewer wherever possible. * End comments with a full stop. * No emoji, unless you know what you're doing and for whom. ## Universal rules ### Don't pad the obvious If a function's name and signature already say what needs saying, a one-line comment is enough. This guide describes what to do when there is something useful to explain; it does not require restating the obvious. A helper called `toDataURL(source)` that encodes a Python source string as a `data:` URL does not need three paragraphs: > Encode a Python source string as a `data:` URL, suitable for inline file > content in BFP's configuration. That is already the right shape: direct, accurate and efficient. ### Length A reader should be able to grasp the essential purpose and usage within five minutes. If not, simplify or restructure it. Deep dives belong elsewhere and should be linked. ### Trusted sources When linking out for further reading, prefer the project's own documentation, then its upstream foundations, then the family's shared authorities: * Mozilla Developer Network for web platform topics: `https://developer.mozilla.org` * the official Python documentation: `https://docs.python.org` * the official MicroPython documentation: `https://docs.micropython.org` * the official Pyodide documentation: `https://pyodide.org` Prefer authoritative, durable sources for foundational technical facts. ### When in doubt Read the commentary as one of the project's practitioners. Does it inform them accurately? Does it respect their intelligence without assuming their expertise? Would it make someone who is unsure whether they belong feel especially welcome rather than warily tolerated? If so, it is doing its job. If it postures, hedges, repeats their reasoning back to them or tries to persuade them that the API is worth using, it is in the way. ## Python specifics Python docstrings need no tags. The shapes above, written as flowing prose, are the convention. Code examples use a `python` language hint. ### A worked example Here is the shape of a fully documented public function: ````python def web_request(url, result_key, method="GET", body=None, response_format="json"): """ Fetch data from a URL and store the response in the datastore. The request runs as a background task: the call returns immediately, and the response arrives later under `result_key` in the datastore, where subscribed code or a bound widget will receive it. The `url` names the resource to fetch. The `method` is the HTTP method to use, "GET" unless stated. A `body`, when given, is sent with the request - the usual companion to "POST". The `response_format` says how to interpret what comes back: "json" for structured data, "text" for plain text, or "bytes" for raw binary content. Raises `ValueError` if `url` is empty, or if `response_format` is not one of the recognised formats. ```python # GET as JSON. web_request("https://example.com/data", result_key="data") # POST with a body. web_request("https://example.com/save", result_key="ack", method="POST", body=payload) # GET as raw bytes. web_request("https://example.com/sound.ogg", result_key="audio", response_format="bytes") ``` """ ```` ## JavaScript specifics JSDoc is both documentation and part of the type system in our JavaScript projects. Keep the set of tags deliberately small. ### Behaviour tags * `@param {Type} name - description` - one per argument, in declaration order. Explain the argument's intent, not merely its type. * `@returns {Type} description` - what the function gives back and what the caller will find useful about it. Omit for functions that return `undefined`. * `@throws {ErrorType} description` - one per distinct error condition. Describe the condition that causes the throw, not just the error class. * `@example` - a fenced code block showing real usage. Multiple examples are welcome when they contrast rather than repeat. ### Type tags * `@typedef` - declares a type used elsewhere in the source. It lives in a `types.js` module or alongside the code that uses it. * `@type {Type}` - annotates a variable or property whose type cannot be inferred. * `@callback` - declares the signature of a callback type used in hooks and options. ### Tags we avoid * `@author`, `@since`, `@version` - git history records this better. * `@description` - the leading prose is already the description. * `@summary` - the first sentence already serves as the summary. ### Type annotations match the prose The types declared in `@param`, `@returns` and `@throws` are not decoration. They are read by `tsc --checkJs` and must accurately describe what the code actually accepts and returns. When the prose says "an object with `id` and `src` properties", the type must say the same thing, with the same property names. When the prose says "a string or a configuration object", the type must be the union of those two. If a type cannot be expressed inline, define it once with `@typedef` and refer to the named type from then on. Typedef names follow the conventions of the code: descriptive, human-meaningful and PascalCase. ### A worked example Here is the shape of a fully documented public function: ````javascript /** * Create a new BFP execution context. * * @param {object} options - the context's configuration. * @param {string} options.id - identifier for the context. * `"__main__"` for the main thread; any other string declares * a worker. * @param {string} [options.src] - URL of the Python source to * fetch and run at startup. Mutually exclusive with `code`. * @param {string} [options.code] - Python source to run at * startup, supplied directly. Mutually exclusive with `src`. * Supplying neither is valid: the context starts and waits to * be driven via `eval`/`exec`. * @param {"py" | "mpy"} [options.type="py"] - runtime selector. * @param {object | string} [options.config] - configuration * object, or URL of a JSON configuration file. * @param {boolean} [options.debug=false] - run the runtime in * debug mode. * @param {string} [options.target] - id of the DOM element for * output (main-thread only). * @param {boolean | "raw"} [options.terminal] - create an * XTerm-based terminal (main-thread only). * @param {number} [options.terminalRows] - explicit terminal row * count; a positive integer (main-thread only). Requires * `terminal`. Each dimension is resolved independently: one * given here is honoured, one left unset is fitted to the * target element. The names mirror XTerm's own init-only * options (`rows`/`cols`), to which the values pass straight * through. * @param {number} [options.terminalCols] - explicit terminal column * count; a positive integer (main-thread only). As `terminalRows`. * @param {Function} [options.onResourceLoad] - called when a resource * (a file, package, etc.) is successfully loaded. * @param {Function} [options.onReady] - called when the context is ready. * @param {Function} [options.onError] - called when an error occurs. * @param {Function} [options.onOutput] - called when there is output from * the context (main-thread only). * @param {Function} [options.onInput] - called when input is requested * from the context (main-thread only). * @param {Function} [options.onTerminating] - called when the context is * terminating. * @param {Function} [options.onMessage] - called when a message is received * from the context (worker context only). * @returns {Promise} the context handle. * @throws {BFPError} if required options are missing. * @throws {BFPContextExistsError} if `id` is already in use. * * @example * ```javascript * const main = await bfp.startPython({ * id: "__main__", * src: "./main.py", * onReady: () => console.log("ready"), * }); * ``` */ export async function startPython(options) { // ... } ````