Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
148103 stories
·
33 followers

copilot-instructions.md

1 Share

When working with CoPilot in Visual Studio, the single most important thing is context. Context tells CoPilot what it is working on, what it should already know, what language conventions to use, etc., etc. CoPilot wants to help, but its memory is not the best, and like the character in Memento, the trick is to write everything down and remind it all the time… hence context.

The best way to get ahead of this is to create a copilot-instructions.md file in your .github directory (which you may need to create). In this file, you’ll want to put anything that CoPilot should know right from the get-go and for every session.

But how do you know what to put in there?

Here’s the trick… let CoPilot build it for you! I cribbed a set of instructions from the ‘net that tells CoPilot how to create the file based on the existing code in my project. I tweaked it just a bit, as did a buddy (Teja) and all you need to do is copy it into the CoPilot window in Visual Studio, let CoPilot cook, and hey! presto! you have just what you want: a fully developed copilot-instructions.md file in just the right place. Even better, if you already have one, this will merge cleanly.

Here’s the instructions I give CoPilot:

Analyze this codebase to generate or update .github/copilot-instructions.md for guiding AI coding agents. Focus on discovering the essential knowledge that would help an AI agent be immediately productive in this codebase. Consider aspects like: The “big picture” architecture that requires reading multiple files to understand – major components, service boundaries, data flows, and the “why” behind structural decisions Critical developer workflows (builds, tests, debugging) especially commands that aren’t obvious from file inspection alone Project-specific conventions and patterns that differ from common practices Integration points, external dependencies, and cross-component communication patterns Guidelines (read more at https://aka.ms/vscode-instructions-docs):

If .github/copilot-instructions.md exists, merge intelligently – preserve valuable content while updating outdated sections Write concise, actionable instructions (~20-50 lines) using markdown structure Include specific examples from the codebase when describing patterns Avoid generic advice (“write tests”, “handle errors”) – focus on THIS project’s specific approaches Document only discoverable patterns, not aspirational practices Maintaining a history or features listing with a detailed description of all the information of the project into a README.md file whenever there is a new change. Update the file accordingly with a brief summary. Before each task implementation, go through the README.md file, then start implementing, understanding the whole picture of the requirements. Reference key files/directories that exemplify important patterns Update .github/copilot-instructions.md for the user, then ask for feedback on any unclear or incomplete sections to iterate.

When writing unit tests use xunit and moq

And here is the markdown file that CoPilot generated for me (put this into a file and open it in VS to see it displayed nicely):

# GitHub Copilot Instructions for HyperVideo

HyperVideo is an interactive video learning platform built with **.NET 10** and **Blazor Server**. Users can pause videos, ask questions, and search multiple knowledge sources for learning resources.

## Project Structure

```
HyperVideo/
├── Components/
│   ├── App.razor               # Root component (HTML shell, Bootstrap, Blazor script)
│   ├── Routes.razor            # Router with 404 fallback and default layout
│   ├── _Imports.razor          # Global using directives for all components
│   ├── Layout/
│   │   ├── MainLayout.razor    # Two-column layout: sidebar NavMenu + main content area
│   │   ├── NavMenu.razor       # Navigation links (Home, Video Learning, Counter, Weather)
│   │   └── ReconnectModal.razor # SignalR reconnection overlay
│   └── Pages/
│       ├── Home.razor          # Landing page with link to video learning
│       ├── VideoLearning.razor # Core feature: interactive video player with inquiry panel
│       ├── Counter.razor       # Simple stateful counter demo
│       ├── Weather.razor       # Async data fetch demo with streaming render
│       ├── Error.razor         # Error boundary page
│       └── NotFound.razor      # 404 page
├── wwwroot/
│   ├── app.css                 # Global styles
│   └── lib/                   # Bootstrap 5 CSS/JS
├── Program.cs                  # App startup and middleware pipeline
├── appsettings.json
└── HyperVideo.csproj
```

## Technology Stack

- **Runtime**: .NET 10 (`net10.0`)
- **UI**: Blazor Server with Interactive Server rendering (`@rendermode InteractiveServer`)
- **Real-time**: ASP.NET Core SignalR (used implicitly by Blazor Server)
- **CSS**: Bootstrap 5, Bootstrap Icons (`bi-*`), component-scoped CSS files (`.razor.css`)
- **JS Interop**: `IJSRuntime` for controlling the HTML5 `<video>` element
- **Nullable**: enabled; **ImplicitUsings**: enabled

## Coding Conventions

### Blazor Components
- Place all pages under `Components/Pages/` with `@page "/route"` directives.
- Place shared layout under `Components/Layout/`.
- Use `@rendermode InteractiveServer` on pages that need interactivity (event handlers, JS interop).
- Component-scoped CSS goes in a sibling file named `ComponentName.razor.css`.
- Use `@code { }` blocks at the bottom of `.razor` files for C# logic.

### C# Style
- Follow standard C# conventions: PascalCase for types and methods, camelCase for private fields.
- Prefer `record` types for immutable data (e.g., `TranscriptSegment`).
- Use nullable reference types; annotate `string?` where null is expected.
- Use `string.Empty` instead of `""` for empty-string defaults.
- Prefer `async Task` over `async void` for event handlers.

### JavaScript Interop
- Inject `IJSRuntime` with `@inject IJSRuntime JS`.
- Prefer `JS.InvokeVoidAsync` for fire-and-forget calls and `JS.InvokeAsync<T>` when a return value is needed.
- Avoid `eval()` for new interop code; instead, expose named JavaScript functions in `wwwroot/` and call them by name.
- Always wrap JS interop calls in `try/catch` because the circuit may not be ready.

### State Management
- Use private fields and `StateHasChanged()` for local component state.
- Keep models close to where they are used; only extract to a separate file when shared across multiple components.

### Error Handling
- Wrap async event handlers in `try/catch` and log errors with `Console.WriteLine` or an injected `ILogger<T>`.
- Use the `Error.razor` page as the global error boundary (already wired via `<ErrorBoundary>`).

## Key Feature: VideoLearning.razor

`VideoLearning.razor` is the core component. Its responsibilities:

| Concern | Implementation |
|---|---|
| Video playback | HTML5 `<video>` element; JS interop to call `.pause()`, `.play()`, seek |
| Pause & Inquire | Sets `isPaused = true`, shows inquiry panel with timestamp |
| Question search | Builds URL links to Wikipedia, Wiktionary, YouTube, Stack Overflow, MDN |
| Transcript | `List<TranscriptSegment>` displayed as clickable rows; active row highlighted |
| Time tracking | `@ontimeupdate` reads `currentTime` via JS interop |

When extending this component:
- Add new search sources by appending to `searchResults` inside `SearchForAnswer()`.
- Add transcript segments by adding `new TranscriptSegment(start, end, "text")` entries.
- Use `ElementReference` + `JS.InvokeVoidAsync("blazorHelpers.seekVideo", videoElement, time)` style helpers rather than bare `eval()`.

## Common Patterns

### Adding a New Page
```razor
@page "/my-page"
@rendermode InteractiveServer

<PageTitle>My Page</PageTitle>

<!-- markup -->

@code {
    // component logic
}
```
Then add a `<NavLink>` entry in `NavMenu.razor`.

### Injecting a Service
Register in `Program.cs`:
```csharp
builder.Services.AddScoped<IMyService, MyService>();
```
Inject in component:
```razor
@inject IMyService MyService
```

### JS Interop Helper Pattern
Add a function to `wwwroot/app.js` (create if it does not exist):
```javascript
window.blazorHelpers = {
    seekVideo: (element, time) => { element.currentTime = time; }
};
```
Call from C#:
```csharp
await JS.InvokeVoidAsync("blazorHelpers.seekVideo", videoElement, time);
```

## Build & Run

```bash
# Restore and run
 dotnet run --project HyperVideo/HyperVideo.csproj

# Build only
dotnet build HyperVideo/HyperVideo.csproj
```

Default URLs: `http://localhost:5092` / `https://localhost:7288`

## What to Avoid

- Do **not** use `@rendermode InteractiveWebAssembly` — this project is Blazor Server only.
- Do **not** add NuGet packages without checking compatibility with `net10.0`.
- Do **not** use bare `eval()` strings for new JS interop; prefer named helper functions.
- Do **not** use `async void` event handlers; use `async Task` and handle exceptions.
- Do **not** store secrets in `appsettings.json`; use environment variables or the .NET Secret Manager.

This is based on the skeleton program written in the past couple of postings, so it didn’t have all that much to go on. Nonetheless, it created a great context file with very specific instructions for CoPilot that will create a consistent interface and programming approach.

More to come as we develop HyperVideo but this will put us on the right track straight away.

Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

IOBluetooth for .NET Refreshed

1 Share
Some time ago, I embarked on a binding library for the macOS IOBluetooth framework. This provides functionality for classic Bluetooth, Hands-free and Object Exchange functionality. It was built for Xamarin Mac and needed a big overhaul to support newer .NET versions. Today I’ve release a pre-release package for version 1.2. This is build with .NET […]

Read the whole story
alvinashcraft
12 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

UX Chronicles: A Software Engineer’s Reality Check on Modern Air Travel

1 Share
The article highlights the disappointing state of user experience in air travel, focusing on unreliable software, poor connectivity, and frustrating airline apps. Despite expectations for improvement, airline systems remain outdated and inefficient, causing significant discomfort and dissatisfaction for travelers. The author urges airlines to prioritize user experience as essential.









Read the whole story
alvinashcraft
20 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

When to Use Builder Pattern in C#: Decision Guide with Examples

1 Share

Learn when to use Builder pattern in C# with clear decision criteria, code examples, and scenarios. Understand the signs that indicate Builder is the right choice.

Read the whole story
alvinashcraft
32 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

What will tomorrow look like?

1 Share

How do you organise for tomorrow when nobody knows what tomorrow looks like?

A friend mentioned yesterday that many software organisations are stuck in a vacuum right now. GenAI is clearly affecting them, but they don’t know how, and even less what to do about it.

At first, this surprised me. I definitely see how GenAI is affecting things daily, but mostly it’s accelerating trends that were already in motion. Sure, it’s a jump, a big one. But the direction isn’t entirely new.

That said, I understand that it’s complex to decide what to do. The information overload isn’t helping, is it? And it also doesn’t help to acknowledge that nobody actually knows what’s coming (even though plenty of people sound like they do). In some places there's a pre-hysteria vibe...

But here’s what scares me more than the uncertainty: doing nothing. That’s probably the worst decision right now. In my opinion the best approach is the same as always: make the best decision you can with what you know today, execute and adapt!

To help you do that, here are three things that are still important and true:

1

Context is king. What you should do depends entirely on your situation, not what worked for someone else or what the hype cycle says.

2

Aim for global optima. Maybe coding speed was your bottleneck before (though I suspect not for most). Where will the bottleneck appear now? What unlocks the most value across your entire business?

3

Software architecture still matters, a lot. If your architecture tricks people into creating errors, it will trick GenAI. If it drains your teams’ energy with unnecessary complexity, same goes for GenAI. If it blocks people, it will block AI agents too.

By the way, nobody ever knows what tomorrow looks like. Therefore, embracing change is always a good strategy.

This article was originally published on LinkedIn. Join the discussion and read more here.

Read the whole story
alvinashcraft
56 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Decision speed

1 Share

I confess, I’m a bit obsessed with bottlenecks. Lately, I’ve been thinking a lot about the kind that slow down your flow of change. I’ve gathered a few links below to solutions for common ones. The theme today is decisions. Maybe one of them will help with whatever bottleneck you’re facing right now?

Decision speed

Suzi Edwards-Alexander pointed me to this interesting article by Dave Girouard: “Speed as a Habit”. It focuses on speed for decisions, which is often what slows everything down. He also addresses the common belief that speed is the enemy of quality. I know you can have both. In fact, high quality can help speed, a lot!

Decentralising decisions

Andrew Harmel Law provides an appealing solution for speeding up architecture decisions whilst keeping them sound: decentralise them “correctly”. (Read it here.) We’ve used architecture decision records for a long time, but this approach makes them even more powerful.

Answering certain hard questions quickly and well

Simon Wardley and Tudor Girba are working on a book called Moldable Development. I’ve only read the first four chapters, but they’re very inspiring. A theme is that by creating tiny, context-aware tools for answering questions about a system, speed and quality of decisions might increase dramatically. Again, they can go hand in hand...

From decision to action

An old favourite book of mine, “The Art of Action” by Stephen Bungay, always feels important here. Maybe the overall decision about direction was taken quickly, but how and when is it translated into action? And what action? Taking the decision is often the easy part. “Yes, there’s a strategy, but I just don’t know what I’m supposed to do” might sound awkwardly familiar. It’s about how to correctly decentralise decisions – and action – to where the information is.

Which are your best suggestions?

This article was originally published on LinkedIn. Join the discussion and read more here.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories