Lingara Lingara Docs Guides API Libraries Apps Build Web app
Language: English

The tutor note

Your app can offer Lingara’s tutor one line of context, such as which words the learner just practised, by adding a tutor_note to its reply. The note reaches the tutor only when your manifest declares it and the learner turned it on when they installed your app. To change that choice, the learner uninstalls your app and installs it again.

What Lingara does to it

  • A line break becomes a space.
  • Control characters and direction overrides are removed.
  • A note longer than 280 characters is cut to 280 and ends in …. Characters are counted as Unicode scalar values, not bytes or screen glyphs.
  • A note your manifest does not declare, or the learner did not allow, is dropped.

How the tutor reads it

The tutor reads your note as quoted text from a third party, never as an instruction. A note Lingara’s safety check refuses is dropped, and the learner’s turn goes on without it. The learner never sees the note.

A good note

A good note is one plain fact the tutor can use, such as “The learner just reviewed 5 words from their Japanese plan.” It says what the learner is doing, not what the tutor should do. Leave out instructions, judgements about the learner, and anything the learner did not see on your card.

Code sample language

TypeScript

function withNote(request: AppRenderRequest) {
  const note = planLine(request);
  // Plain text, at most 280 characters; the tutor reads it, the learner does not.
  return note === "" ? todayCard(0) : reply(todayCard(0)).tutorNote(note);
}

Rust

async fn render(seen: Seen, request: AppRenderRequest) -> Result<Reply, BoxError> {
    let (lang, progress) = shared_plan(&request);
    let count = seen.lock().map_err(|_| "poisoned")?.get(&request.subject).copied().unwrap_or(0);
    let card = today_card("Today's five", &lang)?;
    // Plain text the learner's tutor can read: at most 280 characters.
    let note = match progress {
        Some((done, total)) => format!("The learner has reviewed {count} words with this app today; {done} of {total} sets done."),
        None => format!("The learner has reviewed {count} words with this app today."),
    };
    Ok(reply(card).tutor_note(note)?)
}

Go

card, err := lingaraapps.NewCard().Heading("Daily five", 1).Text("雨 · 雪 · 风 · 云 · 雷").Build()
if err != nil {
	return nil, err
}
// Plain text, at most 280 characters, for Lingara's tutor to use.
return lingaraapps.Reply(card).
	TutorNote("The learner is reviewing weather words today."), nil

Java

import com.getlingara.apps.Card;
import com.getlingara.apps.Reply;

Card card = Card.card().heading("Today's five", 1).term("雨", "yǔ", "rain", "zh").build();
// Plain text, at most 280 characters; the tutor reads it beside the card.
return Reply.reply(card).tutorNote("The learner is reviewing weather words today.");

Kotlin

import com.getlingara.apps.kotlin.Reply
import com.getlingara.apps.kotlin.card
import com.getlingara.apps.kotlin.reply

val c =
    card {
        heading("Today's five", 1)
        term("雨", reading = "yǔ", gloss = "rain", lang = "zh")
    }
// Plain text, at most 280 characters; the tutor reads it beside the card.
return reply(c).tutorNote("The learner is reviewing weather words today.")

Ruby

note = plan_line(request)
# Plain text, at most 280 characters; the tutor reads it, the learner does not.
note.empty? ? today_card(0) : Lingara::Apps.reply(today_card(0)).tutor_note(note)

PHP

use Lingara\Apps\Reply;

function withNote(AppRenderRequest $request): CardModel|Reply
{
    $note = planLine($request);
    // Plain text, at most 280 characters; the tutor reads it, the learner does not.
    return $note === '' ? todayCard(0) : Reply::of(todayCard(0))->tutorNote($note);
}